diff --git a/.github/workflows/build_documentation.yml b/.github/workflows/build_documentation.yml
deleted file mode 100644
index 5dfbb3d0d84..00000000000
--- a/.github/workflows/build_documentation.yml
+++ /dev/null
@@ -1,99 +0,0 @@
-name: Documentation Build
-
-on: [pull_request, workflow_dispatch]
-
-env:
- # Following env vars when changed will "reset" the mentioned cache,
- # by changing the cache file name. It is rendered as ...-v%RESET_XXX%-...
- # You should go up in number, if you go down (or repeat a previous value)
- # you might end up reusing a previous cache if it haven't been deleted already.
- # It applies 7 days retention policy by default.
- RESET_EXAMPLES_CACHE: 3
- RESET_DOC_BUILD_CACHE: 3
- RESET_AUTOSUMMARY_CACHE: 3
-
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- docs-style:
- name: "Check documentation style"
- runs-on: ubuntu-latest
- steps:
- - name: "Check documentation style"
- uses: ansys/actions/doc-style@v5
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- vale-config: "doc/.vale.ini"
- vale-version: "2.29.6"
-
- docs_build:
- runs-on: ubuntu-20.04
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.10"
-
- - name: Update pip
- run: |
- pip install --upgrade pip
-
- - name: Install pyaedt
- run: |
- pip install .[doc]
-
- - name: Verify pyaedt can be imported
- run: python -c "import pyaedt"
-
- - name: Retrieve PyAEDT version
- id: version
- run: |
- echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT
- echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")"
-
- # - name: Cache docs build directory
- # uses: actions/cache@v3
- # with:
- # path: doc/build
- # key: doc-build-v${{ env.RESET_DOC_BUILD_CACHE }}-${{ steps.version.outputs.PYAEDT_VERSION }}-${{ github.sha }}
- # restore-keys: |
- # doc-build-v${{ env.RESET_DOC_BUILD_CACHE }}-${{ steps.version.outputs.PYAEDT_VERSION }}
- # - name: Cache autosummary
- # uses: actions/cache@v3
- # with:
- # path: doc/source/**/_autosummary/*.rst
- # key: autosummary-v${{ env.RESET_AUTOSUMMARY_CACHE }}-${{ steps.version.outputs.PYAEDT_VERSION }}-${{ github.sha }}
- # restore-keys: |
- # autosummary-v${{ env.RESET_AUTOSUMMARY_CACHE }}-${{ steps.version.outputs.PYAEDT_VERSION }}
-
- - name: Install doc build requirements
- run: |
- sudo apt install graphviz
-
- # run doc build, without creating the examples directory
- # note that we have to add the examples file here since it won't
- # be created as gallery is disabled on linux.
- - name: Documentation Build
- run: |
- make -C doc clean
- mkdir doc/source/examples -p
- echo $'Examples\n========' > doc/source/examples/index.rst
- make -C doc html SPHINXOPTS="-j auto -w build_errors.txt -N"
-
- # Verify that sphinx generates no warnings
- - name: Check for warnings
- run: |
- python doc/print_errors.py
-
-# - name: Upload Documentation
-# uses: actions/upload-artifact@v4
-# with:
-# name: Documentation
-# path: doc/_build/html
-# retention-days: 7
diff --git a/.github/workflows/full_documentation.yml b/.github/workflows/full_documentation.yml
index 38364e830ad..68f6a319f48 100644
--- a/.github/workflows/full_documentation.yml
+++ b/.github/workflows/full_documentation.yml
@@ -10,19 +10,19 @@ env:
MEILISEARCH_HOST_URL: https://backend.search.pyansys.com
MEILISEARCH_PUBLIC_API_KEY: ${{ secrets.MEILISEARCH_PUBLIC_API_KEY }}
# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- tags:
- - v*
- workflow_dispatch:
- inputs:
- logLevel:
- description: 'Log level'
- required: true
- default: 'warning'
- tags:
- description: 'Test scenario tags'
+on: [pull_request, workflow_dispatch]
+ # # Triggers the workflow on push or pull request events but only for the main branch
+ # push:
+ # tags:
+ # - v*
+ # workflow_dispatch:
+ # inputs:
+ # logLevel:
+ # description: 'Log level'
+ # required: true
+ # default: 'warning'
+ # tags:
+ # description: 'Test scenario tags'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -34,7 +34,7 @@ jobs:
# The type of runner that the job will run on
name: full_documentation
runs-on: [windows-latest, pyaedt]
- timeout-minutes: 720
+ timeout-minutes: 900
strategy:
matrix:
python-version: ['3.10']
@@ -59,6 +59,7 @@ jobs:
run: |
testenv\Scripts\Activate.ps1
pip install .[doc]
+ pip install .[ci]
Copy-Item -Path "C:\actions-runner\opengl32.dll" -Destination "testenv\Lib\site-packages\vtkmodules" -Force
- name: Retrieve PyAEDT version
@@ -71,7 +72,8 @@ jobs:
- name: Create HTML Documentations
run: |
testenv\Scripts\Activate.ps1
- sphinx-build -j auto --color -b html -a doc/source doc/_build/html
+ cd doc
+ .\make.bat html
# - name: Create PDF Documentations
# run: |
@@ -93,7 +95,7 @@ jobs:
retention-days: 7
# - name: Upload PDF documentation artifact
-# uses: actions/upload-artifact@v4
+# uses: actions/upload-artifact@v3
# with:
# name: documentation-pdf
# path: doc/_build/pdf
diff --git a/.github/workflows/ironpython.yml b/.github/workflows/ironpython.yml
deleted file mode 100644
index b169c44d1c3..00000000000
--- a/.github/workflows/ironpython.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: CI_Ironpython
-
-
-# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- pull_request:
- branches: [ main ]
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: [windows-latest, pyaedt]
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
-
- - name: 'Run Unit Tests in Ironpython'
- timeout-minutes: 60
- run: |
- $processA = start-process 'cmd' -ArgumentList '/c .\_unittest_ironpython\run_unittests_batchmode.cmd' -PassThru
- $processA.WaitForExit()
- get-content .\_unittest_ironpython\pyaedt_unit_test_ironpython.log
- $test_errors_failures = Select-String -Path .\_unittest_ironpython\pyaedt_unit_test_ironpython.log -Pattern "TextTestResult errors="
- if ($test_errors_failures -ne $null)
- {
- exit 1
- }
- else
- {
- exit 0
- }
diff --git a/.github/workflows/nightly-docs.yml b/.github/workflows/nightly-docs.yml
deleted file mode 100644
index bebff44a875..00000000000
--- a/.github/workflows/nightly-docs.yml
+++ /dev/null
@@ -1,133 +0,0 @@
-name: Nightly Documentation Build
-
-on:
- workflow_dispatch:
- schedule: # UTC at 0400
- - cron: '0 4 * * *'
-
-env:
- DOCUMENTATION_CNAME: 'aedt.docs.pyansys.com'
- MEILISEARCH_API_KEY: ${{ secrets.MEILISEARCH_API_KEY }}
- MEILISEARCH_PUBLIC_API_KEY: ${{ secrets.MEILISEARCH_PUBLIC_API_KEY }}
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-jobs:
- docs_build:
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v4
-
- - name: Setup Python
- uses: actions/setup-python@v5
- with:
- python-version: "3.10"
-
- - name: Install pyaedt
- run: |
- pip install .
-
- - name: Install doc build requirements
- run: |
- pip install .[doc]
-
- - name: Full Documentation Build
- run: |
- make -C doc phtml
-
- - name: Upload documentation HTML artifact
- uses: actions/upload-artifact@v4
- with:
- name: documentation-html
- path: doc/_build/html
- retention-days: 7
-
- - name: Upload HTML documentation artifact
- uses: actions/upload-artifact@v4
- with:
- name: documentation-html-edb
- path: doc/_build/html/EDBAPI
- retention-days: 7
-
- docs_upload:
- needs: docs_build
- runs-on: ubuntu-latest
- steps:
-
- - name: Deploy development documentation
- uses: ansys/actions/doc-deploy-dev@v4
- with:
- cname: ${{ env.DOCUMENTATION_CNAME }}
- token: ${{ secrets.GITHUB_TOKEN }}
-
- doc-index-dev:
- name: "Deploy dev docs index"
- runs-on: ubuntu-latest
- needs: docs_upload
- steps:
- - uses: actions/checkout@v4
-
- - uses: actions/download-artifact@v3
-
- - name: Display structure of downloaded files
- run: ls -R
-
- - name: "Deploy the dev documentation index for PyAEDT API"
- uses: ansys/actions/doc-deploy-index@v4
- with:
- cname: ${{ env.DOCUMENTATION_CNAME }}/version/dev
- index-name: pyaedt-vdev
- host-url: ${{ vars.MEILISEARCH_HOST_URL }}
- api-key: ${{ env.MEILISEARCH_API_KEY }}
- pymeilisearchopts: --stop_urls \"EDBAPI\" # Add EDB API as another index to show it in dropdown button
-
- - name: "Deploy the dev documentation index for EDB API"
- uses: ansys/actions/doc-deploy-index@v4
- with:
- cname: ${{ env.DOCUMENTATION_CNAME }}/version/dev/EDBAPI/
- index-name: pyedb-vdev
- host-url: ${{ vars.MEILISEARCH_HOST_URL }}
- api-key: ${{ env.MEILISEARCH_API_KEY }}
- doc-artifact-name: documentation-html-edb # Add only EDB API as page in this index.
- pymeilisearchopts: --port 8001 # serve in another port as 8000 is deafult
-
- # docstring_testing:
- # runs-on: Windows
-
- # steps:
- # - uses: actions/checkout@v4
-
- # - name: Setup Python
- # uses: actions/setup-python@v2
- # with:
- # python-version: 3.8
-
- # - name: 'Create virtual env'
- # run: |
- # python -m venv testenv
- # testenv\Scripts\Activate.ps1
- # python -m pip install pip -U
- # python -m pip install wheel setuptools -U
- # python -c "import sys; print(sys.executable)"
-
- # - name: 'Install pyaedt'
- # run: |
- # testenv\Scripts\Activate.ps1
- # pip install . --use-feature=in-tree-build
- # cd _unittest
- # python -c "import pyaedt; print('Imported pyaedt')"
-
- # - name: Install testing requirements
- # run: |
- # testenv\Scripts\Activate.ps1
- # pip install -r requirements/requirements_test.txt
- # pip install pytest-azurepipelines
-
- # - name: Docstring testing
- # run: |
- # testenv\Scripts\Activate.ps1
- # pytest -v pyaedt/desktop.py pyaedt/icepak.py
- # pytest -v pyaedt/desktop.py pyaedt/hfss.py
diff --git a/.github/workflows/unit_tests.yml b/.github/workflows/unit_tests.yml
deleted file mode 100644
index 2dcee8a270d..00000000000
--- a/.github/workflows/unit_tests.yml
+++ /dev/null
@@ -1,172 +0,0 @@
-name: CI
-
-env:
- python.version: '3.10'
- python.venv: 'testvenv'
- # Following env vars when changed will "reset" the mentioned cache,
- # by changing the cache file name. It is rendered as ...-v%RESET_XXX%-...
- # You should go up in number, if you go down (or repeat a previous value)
- # you might end up reusing a previous cache if it hasn't been deleted already.
- # It applies 7 days retention policy by default.
- RESET_PIP_CACHE: 0
- PACKAGE_NAME: PyAEDT
-# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- tags:
- - 'v*'
- branches:
- - main
- pull_request:
- branches: [ main ]
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build_solvers:
- # The type of runner that the job will run on
- runs-on: [ windows-latest, pyaedt ]
- strategy:
- matrix:
- python-version: [ '3.10' ]
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: 'Create virtual env'
- run: |
- Remove-Item D:\Temp\* -Recurse -Force -ErrorAction SilentlyContinue
- python -m venv testenv_s
- testenv_s\Scripts\Activate.ps1
- python -m pip install pip -U
- python -m pip install wheel setuptools -U
- python -c "import sys; print(sys.executable)"
-
- - name: 'Install pyaedt'
- run: |
- testenv_s\Scripts\Activate.ps1
- pip install .
- pip install .[tests]
- pip install pytest-azurepipelines
- Copy-Item -Path "C:\actions-runner\opengl32.dll" -Destination "testenv_s\Lib\site-packages\vtkmodules" -Force
- mkdir tmp
- cd tmp
- python -c "import pyaedt; print('Imported pyaedt')"
-
- # - name: "Check licences of packages"
- # uses: pyansys/pydpf-actions/check-licenses@v2.0
-
- - name: 'Unit testing'
- uses: nick-fields/retry@v3
- with:
- max_attempts: 3
- retry_on: error
- timeout_minutes: 40
- command: |
- testenv_s\Scripts\Activate.ps1
- Set-Item -Path env:PYTHONMALLOC -Value "malloc"
- pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers
-
- - uses: codecov/codecov-action@v4
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- with:
- name: 'Upload coverage to Codecov'
-
- - name: Upload pytest test results
- uses: actions/upload-artifact@v4
- with:
- name: pytest-solver-results
- path: junit/test-results.xml
- # Use always() to always run this step to publish test results when there are test failures
- if: ${{ always() }}
-
-
- build:
- # The type of runner that the job will run on
- runs-on: [windows-latest, pyaedt]
- strategy:
- matrix:
- python-version: ['3.10']
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: 'Create virtual env'
- run: |
- Remove-Item D:\Temp\* -Recurse -Force -ErrorAction SilentlyContinue
- python -m venv testenv
- testenv\Scripts\Activate.ps1
- python -m pip install pip -U
- python -m pip install wheel setuptools -U
- python -c "import sys; print(sys.executable)"
-
- - name: 'Install pyaedt'
- run: |
- testenv\Scripts\Activate.ps1
- pip install .
- pip install .[tests]
- pip install pytest-azurepipelines
- Copy-Item -Path "C:\actions-runner\opengl32.dll" -Destination "testenv\Lib\site-packages\vtkmodules" -Force
- mkdir tmp
- cd tmp
- python -c "import pyaedt; print('Imported pyaedt')"
-
- # - name: "Check licences of packages"
- # uses: pyansys/pydpf-actions/check-licenses@v2.0
-
- - name: 'Unit testing'
- uses: nick-fields/retry@v3
- with:
- max_attempts: 3
- retry_on: error
- timeout_minutes: 50
- command: |
- testenv\Scripts\Activate.ps1
- Set-Item -Path env:PYTHONMALLOC -Value "malloc"
- pytest -n 6 --dist loadfile --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest
-
- - uses: codecov/codecov-action@v4
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- with:
- name: 'Upload coverage to Codecov'
-
- - name: Upload pytest test results
- uses: actions/upload-artifact@v4
- with:
- name: pytest-results
- path: junit/test-results.xml
- # Use always() to always run this step to publish test results when there are test failures
- if: ${{ always() }}
-
- - name: 'Build and validate source distribution'
- run: |
- testenv\Scripts\Activate.ps1
- python -m pip install build twine
- python -m build
- python -m twine check dist/*
-
- - name: "Builds and uploads to PyPI"
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- run: |
- testenv\Scripts\Activate.ps1
- python setup.py sdist
- python -m pip install twine
- python -m twine upload --skip-existing dist/*
- env:
- TWINE_USERNAME: __token__
- TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/unit_tests_solvers.bkp b/.github/workflows/unit_tests_solvers.bkp
deleted file mode 100644
index 19080841594..00000000000
--- a/.github/workflows/unit_tests_solvers.bkp
+++ /dev/null
@@ -1,103 +0,0 @@
-name: CI_Solvers
-
-env:
- python.version: '3.10'
- python.venv: 'testvenv'
- # Following env vars when changed will "reset" the mentioned cache,
- # by changing the cache file name. It is rendered as ...-v%RESET_XXX%-...
- # You should go up in number, if you go down (or repeat a previous value)
- # you might end up reusing a previous cache if it hasn't been deleted already.
- # It applies 7 days retention policy by default.
- RESET_PIP_CACHE: 0
- PACKAGE_NAME: PyAEDT
-# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- tags:
- - 'v*'
- branches:
- - main
- pull_request:
- branches: [ main ]
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: [windows-latest, pyaedt]
- strategy:
- matrix:
- python-version: ['3.10']
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v4
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: 'Create virtual env'
- run: |
- Remove-Item D:\Temp\* -Recurse -Force
- python -m venv testenv_s
- testenv_s\Scripts\Activate.ps1
- python -m pip install pip -U
- python -m pip install wheel setuptools -U
- python -c "import sys; print(sys.executable)"
-
- - name: 'Install pyaedt'
- run: |
- testenv_s\Scripts\Activate.ps1
- pip install .
- pip install .[tests]
- pip install pytest-azurepipelines
- Copy-Item -Path "C:\actions-runner\opengl32.dll" -Destination "testenv_s\Lib\site-packages\vtkmodules" -Force
- mkdir tmp
- cd tmp
- python -c "import pyaedt; print('Imported pyaedt')"
-
- # - name: "Check licences of packages"
- # uses: pyansys/pydpf-actions/check-licenses@v2.0
-
- - name: 'Unit testing'
- timeout-minutes: 40
- run: |
- testenv_s\Scripts\Activate.ps1
- Set-Item -Path env:PYTHONMALLOC -Value "malloc"
- pytest --durations=50 -v --cov=pyaedt --cov-report=xml --cov-report=html --junitxml=junit/test-results.xml _unittest_solvers
-
- - uses: codecov/codecov-action@v3
- if: matrix.python-version == '3.10'
- name: 'Upload coverage to Codecov'
-
- - name: Upload pytest test results
- uses: actions/upload-artifact@v3
- with:
- name: pytest-results
- path: junit/test-results.xml
- # Use always() to always run this step to publish test results when there are test failures
- if: ${{ always() }}
-
- - name: 'Build and validate source distribution'
- run: |
- testenv_s\Scripts\Activate.ps1
- python -m pip install build twine
- python -m build
- python -m twine check dist/*
-
- - name: "Builds and uploads to PyPI"
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- run: |
- testenv_s\Scripts\Activate.ps1
- python setup.py sdist
- python -m pip install twine
- python -m twine upload --skip-existing dist/*
- env:
- TWINE_USERNAME: __token__
- TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
diff --git a/.github/workflows/wheelhouse.yml b/.github/workflows/wheelhouse.yml
deleted file mode 100644
index 3b8e2631955..00000000000
--- a/.github/workflows/wheelhouse.yml
+++ /dev/null
@@ -1,90 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: WheelHouse
-
-env:
- python.venv: 'testvenv'
- # Following env vars when changed will "reset" the mentioned cache,
- # by changing the cache file name. It is rendered as ...-v%RESET_XXX%-...
- # You should go up in number, if you go down (or repeat a previous value)
- # you might end up reusing a previous cache if it haven't been deleted already.
- # It applies 7 days retention policy by default.
- RESET_PIP_CACHE: 0
- PACKAGE_NAME: PyAEDT
-# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- tags:
- - 'v*'
- - v*
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: [windows-latest]
- strategy:
- matrix:
- python-version: [ 3.7, 3.8, 3.9, '3.10']
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: 'Create virtual env'
- run: |
- python -m venv testenv
- testenv\Scripts\Activate.ps1
- python -m pip install pip -U
- python -m pip install wheel setuptools -U
- python -c "import sys; print(sys.executable)"
- pip install .[all]
- pip install jupyterlab
-
-
- - name: Retrieve PyAEDT version
- run: |
- testenv\Scripts\Activate.ps1
- echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT
- echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")"
- id: version
-
- - name: Generate wheelhouse
- run: |
- testenv\Scripts\Activate.ps1
- $packages=$(pip freeze)
- # Iterate over the packages and generate wheels
- foreach ($package in $packages) {
- echo "Generating wheel for $package"
- pip wheel "$package" -w wheelhouse
- }
-
- - name: Zip wheelhouse
- uses: vimtor/action-zip@v1
- with:
- files: wheelhouse
- dest: ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-${{ runner.os }}-${{ matrix.python-version }}.zip
-
- - name: Upload Wheelhouse
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-${{ runner.os }}-${{ matrix.python-version }}
- path: '*.zip'
- retention-days: 7
-
- - name: Release
- uses: softprops/action-gh-release@v1
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- with:
- generate_release_notes: true
- files: |
- ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-${{ runner.os }}-${{ matrix.python-version }}.zip
diff --git a/.github/workflows/wheelhouse_linux.yml b/.github/workflows/wheelhouse_linux.yml
deleted file mode 100644
index c3d61262668..00000000000
--- a/.github/workflows/wheelhouse_linux.yml
+++ /dev/null
@@ -1,89 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: WheelHouse Linux
-
-env:
- python.venv: 'testvenv'
- # Following env vars when changed will "reset" the mentioned cache
- # by changing the cache file name. It is rendered as ...-v%RESET_XXX%-...
- # You should go up in number. If you go down (or repeat a previous value),
- # you might end up reusing a previous cache if it hasn't been deleted already.
- # It applies a 7-day retention policy by default.
- RESET_PIP_CACHE: 0
- PACKAGE_NAME: PyAEDT
-# Controls when the workflow will run
-on:
- # Triggers the workflow on push or pull request events but only for the main branch
- push:
- tags:
- - 'v*'
- - v*
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: ubuntu-20.04
- strategy:
- matrix:
- python-version: [ 3.7, 3.8, 3.9, '3.10']
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
-
- - name: Install pyaedt
- run: |
- pip install .[all]
- pip install jupyterlab
-
- - name: Verify pyaedt can be imported
- run: python -c "import pyaedt"
-
- - name: Retrieve PyAEDT version
- run: |
- echo "PYAEDT_VERSION=$(python -c 'from pyaedt import __version__; print(__version__)')" >> $GITHUB_OUTPUT
- echo "PyAEDT version is: $(python -c "from pyaedt import __version__; print(__version__)")"
- id: version
-
- - name: Generate wheelhouse
- run: |
- pip install wheel setuptools -U
- pip install --upgrade pip
- pip wheel . -w wheelhouse
- export wheellist=$(pip freeze)
- for file in $wheellist; do
- if [[ $file != *"@"* ]] && [[ $file != *"pyaedt"* ]]; then
- pip wheel $file -w wheelhouse
- fi
- done
- continue-on-error: true
-
- - name: Zip wheelhouse
- uses: vimtor/action-zip@v1
- with:
- files: wheelhouse
- dest: ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-wheelhouse-${{ runner.os }}-${{ matrix.python-version }}.zip
-
- - name: Upload Wheelhouse
- uses: actions/upload-artifact@v4
- with:
- name: ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-wheelhouse-${{ runner.os }}-${{ matrix.python-version }}
- path: '*.zip'
- retention-days: 7
-
- - name: Release
- uses: softprops/action-gh-release@v1
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
- with:
- generate_release_notes: true
- files: |
- ${{ env.PACKAGE_NAME }}-v${{ steps.version.outputs.PYAEDT_VERSION }}-wheelhouse-${{ runner.os }}-${{ matrix.python-version }}.zip
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 32172648189..0af6f3e1d03 100644
--- a/.gitignore
+++ b/.gitignore
@@ -381,6 +381,9 @@ test-output.xml
# Scratch Jupyter Notebooks
scratch_notebooks/
+# Ipython notebook checkpoints
+.ipynb_checkpoints
+
# Visual studio code local settings
.vscode/
diff --git a/doc/make.bat b/doc/make.bat
index 5c169485edb..d5a0a904a40 100644
--- a/doc/make.bat
+++ b/doc/make.bat
@@ -11,6 +11,8 @@ set SOURCEDIR=source
set BUILDDIR=_build
if "%1" == "" goto help
+if "%1" == "clean" goto clean
+if "%1" == "html" goto html
if "%1" == "pdf" goto pdf
%SPHINXBUILD% >NUL 2>NUL
@@ -32,11 +34,37 @@ goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+:clean
+rmdir /s /q %SOURCEDIR%\%BUILDDIR%
+for /d /r %SOURCEDIR% %%d in (_autosummary) do @if exist "%%d" rmdir /s /q "%%d"
+goto end
+
+:html
+%SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% -v %O%
+goto build-examples-py
+
+:build-examples-py
+cd "%BUILDDIR%\html\examples"
+for /d %%D in (*) do (
+Echo Processing examples folder... %%D
+cd %%D
+for %%f in (*.ipynb) do (
+ jupytext --to py "%%f"
+)
+cd ../
+)
+goto end
+
:pdf
%SPHINXBUILD% -M latex %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
cd "%BUILDDIR%\latex"
for %%f in (*.tex) do (
pdflatex "%%f" --interaction=nonstopmode)
+if NOT EXIST pyaedt.pdf (
+ Echo "no pdf generated!"
+ exit /b 1)
+Echo "pdf generated!"
+goto end
:end
popd
diff --git a/doc/source/API/Application.rst b/doc/source/API/Application.rst
deleted file mode 100644
index 87ccb2a90b4..00000000000
--- a/doc/source/API/Application.rst
+++ /dev/null
@@ -1,69 +0,0 @@
-Application and solvers
-=======================
-The PyAEDT API includes classes for different applications available in Ansys Electronics Desktop (AEDT).
-You must initialize AEDT to get access to all PyAEDT modules and methods.
-
-.. image:: ../Resources/aedt_2.png
- :width: 800
- :alt: Ansys Electronics Desktop (AEDT) is a platform that enables true electronics system design.
-
-
-Available PyAEDT apps are:
-
-.. autosummary::
- :toctree: _autosummary
-
- pyaedt.desktop.Desktop
- pyaedt.hfss.Hfss
- pyaedt.q3d.Q3d
- pyaedt.q3d.Q2d
- pyaedt.maxwell.Maxwell2d
- pyaedt.maxwell.Maxwell3d
- pyaedt.icepak.Icepak
- pyaedt.hfss3dlayout.Hfss3dLayout
- pyaedt.mechanical.Mechanical
- pyaedt.rmxprt.Rmxprt
- pyaedt.circuit.Circuit
- pyaedt.maxwellcircuit.MaxwellCircuit
- pyaedt.emit.Emit
- pyaedt.twinbuilder.TwinBuilder
-
-
-All other classes and methods are inherited into the app class.
-AEDT, which is also referred to as the desktop app, is implicitly launched in any PyAEDT app.
-Before accessing a PyAEDT app, the desktop app must be launched and initialized.
-The desktop app can be explicitly or implicitly initialized as in the following examples.
-
-Example with ``Desktop`` class explicit initialization:
-
-.. code:: python
-
- from pyaedt import launch_desktop, Circuit
- d = launch_desktop(specified_version="2023.1",
- non_graphical=False,
- new_desktop_session=True,
- close_on_exit=True,
- student_version=False):
- circuit = Circuit()
- ...
- # Any error here will be caught by Desktop.
- ...
- d.release_desktop()
-
-Example with ``Desktop`` class implicit initialization:
-
-.. code:: python
-
- from pyaedt import Circuit
- circuit = Circuit(specified_version="2023.1",
- non_graphical=False,
- new_desktop_session=True,
- close_on_exit=True,
- student_version=False):
- circuit = Circuit()
- ...
- # Any error here will be caught by Desktop.
- ...
- circuit.release_desktop()
-
-
diff --git a/doc/source/API/Boundaries.rst b/doc/source/API/Boundaries.rst
deleted file mode 100644
index a222340181f..00000000000
--- a/doc/source/API/Boundaries.rst
+++ /dev/null
@@ -1,36 +0,0 @@
-Boundary objects
-================
-This section lists classes for creating and editing
-boundaries in the 3D tools. These objects are returned by
-app methods and can be used to edit or delete a boundary condition.
-
-
-.. currentmodule:: pyaedt.modules.Boundary
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- NativeComponentObject
- BoundaryObject
- BoundaryObject3dLayout
- FarFieldSetup
- Matrix
- BoundaryObject3dLayout
- Sources
- Excitations
-
-Example without ``Native Component Object``:
-
-.. code:: python
-
- from pyaedt import Icepak
- ipk = Icepak()
- component_name = "RadioBoard1"
- native_comp = self.aedtapp.create_ipk_3dcomponent_pcb(
- component_name, link_data, solution_freq, resolution, custom_x_resolution=400, custom_y_resolution=500
- )
- # native_comp is a NativeComponentObject
- ...
- ipk.release_desktop()
-
diff --git a/doc/source/API/CableModeling.rst b/doc/source/API/CableModeling.rst
deleted file mode 100644
index 8166b35acca..00000000000
--- a/doc/source/API/CableModeling.rst
+++ /dev/null
@@ -1,132 +0,0 @@
-Cable modeling
-==============
-The ``Cable Modeling`` module includes several methods to work
-with the Cable Modeling HFSS Beta feature:
-
-
-* ``create_cable`` to create all available types of cables: bundle, straight wire and twisted pair.
-* ``update_cable_properties`` to update all cables properties for all cable types.
-* ``update_shielding`` to update only the shielding jacket type for bundle cable.
-* ``remove_cables`` to remove cables.
-* ``add_cable_to_bundle`` to add a cable or a list of cables to a bundle.
-* ``create_clock_source`` to create a clock source.
-* ``update_clock_source`` to update a clock source.
-* ``remove_source`` to remove a source.
-* ``remove_all_sources`` to remove all sources.
-* ``create_pwl_source`` to create a pwl source.
-* ``create_pwl_source_from_file`` to create a pwl source from file.
-* ``update_pwl_source`` to update a pwl source.
-* ``create_cable_harness`` to create a cable harness.
-
-They are accessible through:
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- CableModeling.Cable
-
-Cable bundle creation example:
-
-.. code:: python
-
- from pyaedt import Hfss
- from pyaedt.generic.DataHandlers import json_to_dict
- from pyaedt.modules.CableModeling import Cable
-
- hfss = Hfss(projectname=project_path, specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
- # This call returns a dictionary out of the JSON file
- cable_props = json_to_dict(json_path)
- # This example shows how to manually change from script the cable properties
- cable_props["Add_Cable"] = "True"
- cable_props["Cable_prop"]["CableType"] = "bundle"
- cable_props["Cable_prop"]["IsJacketTypeInsulation"] = "True"
- cable_props["CableManager"]["Definitions"]["CableBundle"]["BundleParams"]["InsulationJacketParams"][
- "InsThickness"
- ] = "3.66mm"
- cable_props["CableManager"]["Definitions"]["CableBundle"]["BundleParams"]["InsulationJacketParams"][
- "JacketMaterial"
- ] = "pec"
- cable_props["CableManager"]["Definitions"]["CableBundle"]["BundleParams"]["InsulationJacketParams"][
- "InnerDiameter"
- ] = "2.88mm"
- cable_props["CableManager"]["Definitions"]["CableBundle"]["BundleAttribs"]["Name"] = "Bundle_Cable_Insulation"
- # This call returns the Cable class
- cable = Cable(hfss, cable_props)
- # This call creates the cable bundle
- cable.create_cable()
-
-Clock source creation example:
-
-.. code:: python
-
- from pyaedt import Hfss
- from pyaedt.generic.DataHandlers import json_to_dict
- from pyaedt.modules.CableModeling import Cable
-
- hfss = Hfss(projectname=project_path, specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
- # This call returns a dictionary out of the JSON file
- cable_props = json_to_dict(json_path)
- # This example shows how to manually change from script the clock source properties
- cable_props["Add_Cable"] = "False"
- cable_props["Update_Cable"] = "False"
- cable_props["Add_CablesToBundle"] = "False"
- cable_props["Remove_Cable"] = "False"
- cable_props["Add_Source"] = "True"
- cable_props["Source_prop"]["AddClockSource"] = "True"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["Period"] = "40us"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["LowPulseVal"] = "0.1V"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["HighPulseVal"] = "2V"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["Risetime"] = "5us"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["Falltime"] = "10us"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["ClockSignalParams"]["PulseWidth"] = "23us"
- cable_props["CableManager"]["TDSources"]["ClockSourceDef"]["TDSourceAttribs"]["Name"] = "clock_test_1"
- # This call returns the Cable class
- cable = Cable(hfss, cable_props)
- # This call creates the clock source
- cable.create_clock_source()
-
-Cable harness creation example:
-
-.. code:: python
-
- from pyaedt import Hfss
- from pyaedt.generic.DataHandlers import json_to_dict
- from pyaedt.modules.CableModeling import Cable
-
- hfss = Hfss(projectname=project_path, specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
- # This call returns a dictionary out of the JSON file
- cable_props = json_to_dict(json_path)
- # This example shows how to manually change from script the cable harness properties
- cable_props["Add_Cable"] = "False"
- cable_props["Update_Cable"] = "False"
- cable_props["Add_CablesToBundle"] = "False"
- cable_props["Remove_Cable"] = "False"
- cable_props["Add_Source"] = "False"
- cable_props["Update_Source"] = "False"
- cable_props["Remove_Source"] = "False"
- cable_props["Add_CableHarness"] = "True"
- cable_props["CableHarness_prop"]["Name"] = "cable_harness_test"
- cable_props["CableHarness_prop"]["Bundle"] = "New_updated_name_cable_bundle_insulation"
- cable_props["CableHarness_prop"]["TwistAngleAlongRoute"] = "20deg"
- cable_props["CableHarness_prop"]["Polyline"] = "Polyline1"
- cable_props["CableHarness_prop"]["AutoOrient"] = "False"
- cable_props["CableHarness_prop"]["XAxis"] = "Undefined"
- cable_props["CableHarness_prop"]["XAxisOrigin"] = ["0mm", "0mm", "0mm"]
- cable_props["CableHarness_prop"]["XAxisEnd"] = ["0mm", "0mm", "0mm"]
- cable_props["CableHarness_prop"]["ReverseYAxisDirection"] = "True"
- cable_props["CableHarness_prop"]["CableTerminationsToInclude"][0]["CableName"] = "straight_wire_cable"
- cable_props["CableHarness_prop"]["CableTerminationsToInclude"][1]["CableName"] = "straight_wire_cable1"
- cable_props["CableHarness_prop"]["CableTerminationsToInclude"][2]["CableName"] = "straight_wire_cable2"
- # This call returns the Cable class
- cable = Cable(hfss, cable_props)
- # This call creates the cable harness
- cable.create_cable_harness()
\ No newline at end of file
diff --git a/doc/source/API/Configuration.rst b/doc/source/API/Configuration.rst
deleted file mode 100644
index b6284a959c5..00000000000
--- a/doc/source/API/Configuration.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-Configuration files
-~~~~~~~~~~~~~~~~~~~
-This module contains all methods to export project settings to a JSON file
-and import and apply settings to a new design. Currently the configuration
-cover the following apps:
-* HFSS
-* Q2D and Q3D Extractor
-* Maxwell
-* Icepak
-* Mechanical
-
-The sections covered are:
-
-* Variables
-* Mesh operations
-* Setup and optimetrics
-* Material properties
-* Object properties
-* Boundaries and excitations
-
-When a boundary is attached to a face, the tool tries to match it with a
-FaceByPosition on the same object name on the target design. If, for any
-reason, this face position has changed or the object name in the target design has changed,
-the boundary fails to apply.
-
-
-.. currentmodule:: pyaedt.generic.configurations
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- Configurations
- ConfigurationsOptions
- ImportResults
-
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(project_name="original_project", specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- conf_file = self.aedtapp.configurations.export_config()
-
- app2 = Hfss(projec_name='newproject')
- app2.modeler.import_3d_cad(file_path)
- out = app2.configurations.import_config(conf_file)
- app2.configurations.results.global_import_success
-
- ...
diff --git a/doc/source/API/Constants.rst b/doc/source/API/Constants.rst
deleted file mode 100644
index b905b125b64..00000000000
--- a/doc/source/API/Constants.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-Constants
-==========
-This section lists constants that are commonly used in PyAEDT.
-
-
-Example of constants usage:
-
-.. code:: python
-
- from pyaedt import constants
- ipk = Icepak()
- # Use of AXIS Constant
- cylinder = ipk.modeler.create_cylinder(constants.AXIS.X, [0,0,0],10,3)
- # Use of PLANE Constant
- ipk.modeler.split(cylinder, constants.PLANE.YZ, sides="Both")
- ...
- ipk.release_desktop()
-
-
-.. automodule:: pyaedt.generic.constants
- :members:
diff --git a/doc/source/API/DesktopMessenger.rst b/doc/source/API/DesktopMessenger.rst
deleted file mode 100644
index 5d960814d03..00000000000
--- a/doc/source/API/DesktopMessenger.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-Logger
-~~~~~~
-This section lists modules for creating and editing
-PyAEDT log files.
-
-.. currentmodule:: pyaedt.aedt_logger
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- AedtLogger
- AppFilter
diff --git a/doc/source/API/MaterialManagement.rst b/doc/source/API/MaterialManagement.rst
deleted file mode 100644
index 90cdc55479f..00000000000
--- a/doc/source/API/MaterialManagement.rst
+++ /dev/null
@@ -1,56 +0,0 @@
-Material and stackup
-====================
-This section lists material and stackup modules.
-These classes cannot be used directly but can be accessed through an app.
-Example:
-
-
-
-Material management
-~~~~~~~~~~~~~~~~~~~
-This section describes all material-related classes and methods.
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- MaterialLib.Materials
- Material.Material
- Material.SurfaceMaterial
- Material.MatProperties
- Material.SurfMatProperties
- Material.MatProperty
-
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Materials class
- my_materials = app.materials
- # This call returns the Material class
- copper = my_materials["copper"]
- # This property is from the MatProperty class
- copper.conductivity
- ...
-
-
-
-Stackup management
-~~~~~~~~~~~~~~~~~~
-This section describes all layer-related classes and methods used in HFSS 3D Layout (and indirectly in Circuit).
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- LayerStackup.Layers
- LayerStackup.Layer
\ No newline at end of file
diff --git a/doc/source/API/Mesh.rst b/doc/source/API/Mesh.rst
deleted file mode 100644
index 7b1a362ac43..00000000000
--- a/doc/source/API/Mesh.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-Mesh operations
-===============
-The ``Mesh`` module includes these classes:
-
-* ``Mesh`` for HFSS, Maxwell 2D, Maxwell 3D, Q2D Extractor, and Q3D Extractor
-* ``IcepakMesh`` for Icepak
-* ``Mesh3d`` for HFSS 3D Layout
-
-They are accessible through the mesh property:
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- Mesh.Mesh
- MeshIcepak.IcepakMesh
- Mesh3DLayout.Mesh3d
-
-.. code:: python
-
- from pyaedt import Maxwell3d
- app = Maxwell3d(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
- # This call returns the Mesh class
- my_mesh = app.mesh
- # This call executes a Mesh method and creates an object to control the mesh operation
- mesh_operation_object = my_mesh.assign_surface_mesh("MyBox", 2)
- ...
diff --git a/doc/source/API/MultiPartComponent.rst b/doc/source/API/MultiPartComponent.rst
deleted file mode 100644
index e8e192c4aa3..00000000000
--- a/doc/source/API/MultiPartComponent.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-Multi-part components
-=====================
-This section lists classes for creating and editing multi-part components in the 3D tools.
-This consists of a set of one or more 3D component objects, linked together and parametrized
-to allow movements.
-
-
-
-.. currentmodule:: pyaedt.modeler.advanced_cad
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- actors.Person
- actors.Vehicle
- actors.Bird
- actors.Radar
- parts.Part
- parts.Antenna
- multiparts.MultiPartComponent
- multiparts.Environment
- multiparts.Actor
diff --git a/doc/source/API/Optimetrics.rst b/doc/source/API/Optimetrics.rst
deleted file mode 100644
index 6a5e1258642..00000000000
--- a/doc/source/API/Optimetrics.rst
+++ /dev/null
@@ -1,34 +0,0 @@
-Optimetrics
-===========
-This module contains all properties and methods needed to create
-optimetrics setups.
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # returns the ParametericsSetups Class
- app.parametrics
-
- # returns the OptimizationSetups Class
- app.optimizations
-
- # adds an optimization and returns Setup class with all settings and methods
- sweep3 = hfss.opti_optimization.add_optimization(calculation="dB(S(1,1))", calculation_value="2.5GHz")
-
- ...
-
-.. currentmodule:: pyaedt.modules.DesignXPloration
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- ParametricSetups
- OptimizationSetups
- SetupParam
- SetupOpti
-
diff --git a/doc/source/API/Post.rst b/doc/source/API/Post.rst
deleted file mode 100644
index 22cc06f0075..00000000000
--- a/doc/source/API/Post.rst
+++ /dev/null
@@ -1,112 +0,0 @@
-Postprocessing
-==============
-This section lists modules for creating and editing
-plots in AEDT. They are accessible through the ``post`` property.
-
-.. note::
- Some capabilities of the ``AdvancedPostProcessing`` module require Python 3 and
- installations of the `numpy `_,
- `matplotlib `_, and `pyvista `_
- packages.
-
-.. note::
- Some functionalities are available only when AEDT is running
- in graphical mode.
-
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- AdvancedPostProcessing.PostProcessor
- solutions.SolutionData
- solutions.FieldPlot
- solutions.FfdSolutionData
-
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the PostProcessor class
- post = app.post
-
- # This call returns a FieldPlot object
- plotf = post.create_fieldplot_volume(object_list, quantityname, setup_name, intrinsic_dict)
-
- # This call returns a SolutionData object
- my_data = post.get_solution_data(expressions=trace_names)
-
- # This call returns a new standard report object and creates one or multiple reports from it.
- standard_report = post.reports_by_category.standard("db(S(1,1))")
- standard_report.create()
- sols = standard_report.get_solution_data()
- ...
-
-
-AEDT report management
-~~~~~~~~~~~~~~~~~~~~~~
-AEDT provides great flexibility in reports.
-PyAEDT has classes for manipulating any report property.
-
-
-.. note::
- Some functionalities are available only when AEDT is running
- in graphical mode.
-
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- report_templates.Trace
- report_templates.LimitLine
- report_templates.Standard
- report_templates.Fields
- report_templates.NearField
- report_templates.FarField
- report_templates.EyeDiagram
- report_templates.Emission
- report_templates.Spectral
-
-
-Plot fields and data outside AEDT
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-PyAEDT supports external report capabilities available with installed third-party
-packages like `numpy `_,
-`pandas `_, `matplotlib `_,
-and `pyvista `_.
-
-.. currentmodule:: pyaedt.modules
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- solutions.SolutionData
- solutions.FieldPlot
- solutions.FfdSolutionData
- AdvancedPostProcessing.ModelPlotter
-
-
-Icepak monitors
-~~~~~~~~~~~~~~~
-
-.. currentmodule:: pyaedt.modules.monitor_icepak
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- FaceMonitor
- PointMonitor
- Monitor
diff --git a/doc/source/API/Primitive_Objects.rst b/doc/source/API/Primitive_Objects.rst
deleted file mode 100644
index ee4652f3461..00000000000
--- a/doc/source/API/Primitive_Objects.rst
+++ /dev/null
@@ -1,143 +0,0 @@
-Primitives
-==========
-
-This section lists the core AEDT Modeler primitives that are supported both in 2D and 3D solvers (HFSS, Maxwell,
-Icepak, Q3D, and Mechanical):
-
-* Primitives
-* Objects
-
-They are accessible through the ``modeler.objects`` property:
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call return the Modeler3D class
- modeler = app.modeler
-
- # This call returns a Primitives3D object
- primitives = modeler
-
- # This call return an Object3d object
- my_box = primitives.create_box([0,0,0],[10,10,10])
- my_box = primitives.objects[my_box.id]
-
- # This call return a FacePrimitive object list
- my_box.faces
- # This call returns an EdgePrimitive object list
- my_box.edges
- my_box.faces[0].edges
-
- # This call returns a VertexPrimitive object list
- my_box.vertices
- my_box.faces[0].vertices
- my_box.faces[0].edges[0].vertices
-
- ...
-
-
-
-Objects
-~~~~~~~
-
-The following classes define objects properties for 3D and 2D Solvers (excluding HFSS 3D Layout).
-They contain all getters and setters to simplify object manipulation.
-
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- cad.object3d.Object3d
- cad.elements3d.FacePrimitive
- cad.elements3d.EdgePrimitive
- cad.elements3d.VertexPrimitive
- cad.polylines.PolylineSegment
- cad.polylines.Polyline
- cad.component_array.ComponentArray
- cad.components_3d.UserDefinedComponent
- cad.elements3d.Point
- cad.elements3d.Plane
- cad.elements3d.HistoryProps
- cad.elements3d.BinaryTreeNode
-
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Modeler3D class
- modeler = app.modeler
-
- # This call returns a Primitives3D object
- primitives = modeler
-
- # This call returns an Object3d object
- my_box = primitives.create_box([0,0,0],[10,10,10])
-
- # Getter and setter
- my_box.material_name
- my_box.material_name = "copper"
-
- my_box.faces[0].center
-
- ...
-
-
-Coordinate systems and geometry operators
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This module contains all properties and methods needed to edit a
-coordinate system and a set of useful geometry operators.
-The ``CoordinateSystem`` class is accessible through the ``create_coordinate_system``
-method or the ``coordinate_systems`` list. The ``GeometryOperators`` class can be
-imported and used because it is made by static methods.
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- cad.Modeler.CoordinateSystem
- geometry_operators.GeometryOperators
-
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the CoordinateSystem object list
- cs = app.modeler.coordinate_systems
-
- # This call returns a CoordinateSystem object
- new_cs = app.modeler.create_coordinate_system()
-
- ...
-
-
-Advanced modeler operations
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-PyAEDT includes some advanced modeler tools like ``MultiPartComponent`` for 3D component
-management and ``Stackup3D`` for parametric creation of 3D modeler stackups.
-
-.. toctree::
- :maxdepth: 2
-
- MultiPartComponent
- Stackup3D
\ No newline at end of file
diff --git a/doc/source/API/Primitives2D.rst b/doc/source/API/Primitives2D.rst
deleted file mode 100644
index c41e3c5d1d0..00000000000
--- a/doc/source/API/Primitives2D.rst
+++ /dev/null
@@ -1,51 +0,0 @@
-2D modeler
-===========
-
-This section lists the core AEDT Modeler modules for 2D and 3D solvers (Maxwell 2D, 2D Extractor).
-
-
-They are accessible through the ``modeler`` property:
-
-.. code:: python
-
- from pyaedt import Maxwell2d
- app = Maxwell2d(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call return the Modeler2D class
- modeler = app.modeler
-
-
- ...
-
-
-
-The ``Modeler`` module contains all properties and methods needed to edit a
-modeler, including all primitives methods and properties:
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- modeler2d.Modeler2D
-
-
-
-.. code:: python
-
- from pyaedt import Maxwell2d
- app = Maxwell2d(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the NexximComponents class
- origin = [0,0,0]
- dimensions = [10,5,20]
- #Material and name are not mandatory fields
- box_object = app.modeler.primivites.create_rectangle([15, 20, 0], [5, 5], matname="aluminum")
-
- ...
diff --git a/doc/source/API/Primitives3D.rst b/doc/source/API/Primitives3D.rst
deleted file mode 100644
index 186fe639076..00000000000
--- a/doc/source/API/Primitives3D.rst
+++ /dev/null
@@ -1,74 +0,0 @@
-3D modeler
-==========
-
-This section lists the core AEDT Modeler modules with 3D solvers (HFSS, Maxwell,
-Icepak, Q3D, and Mechanical):
-
-* Modeler
-* Primitives
-* Objects
-
-They are accessible through the ``modeler`` property:
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call return the Modeler3D class
- modeler = app.modeler
-
- # This call returns a Primitives3D object
- primitives = modeler
-
- # This call return an Object3d object
- my_box = primitives.create_box([0,0,0],[10,10,10])
- my_box = primitives.objects[my_box.id]
-
- # This call return a FacePrimitive object list
- my_box.faces
- # This call returns an EdgePrimitive object list
- my_box.edges
- my_box.faces[0].edges
-
- # This call returns a VertexPrimitive object list
- my_box.vertices
- my_box.faces[0].vertices
- my_box.faces[0].edges[0].vertices
-
- ...
-
-
-Modeler
-~~~~~~~
-
-The ``Modeler`` module contains all properties and methods needed to edit a
-modeler, including all primitives methods and properties for HFSS, Maxwell 3D, Q3D Extractor, and Icepak:
-
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- modeler3d.Modeler3D
-
-
-.. code:: python
-
- from pyaedt import Circuit
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the NexximComponents class
- origin = [0,0,0]
- dimensions = [10,5,20]
- #Material and name are not mandatory fields
- box_object = app.modeler.primivites.create_box(origin, dimensions, name="mybox", matname="copper")
-
- ...
diff --git a/doc/source/API/Primitives3DLayout.rst b/doc/source/API/Primitives3DLayout.rst
deleted file mode 100644
index c9bb0807cf3..00000000000
--- a/doc/source/API/Primitives3DLayout.rst
+++ /dev/null
@@ -1,81 +0,0 @@
-Modeler in HFSS 3D Layout
-==========================
-
-This section lists the core AEDT Modeler modules available in HFSS 3D Layout:
-
-* Modeler
-* Primitives
-* Objects
-
-They are accessible through the ``modeler`` module and ``modeler.objects`` property:
-
-.. code:: python
-
- from pyaedt import Hfss3dLayout
- hfss = Hfss3dLayout()
- my_modeler = hfss.modeler
-
- ...
-
-
-Modeler
-~~~~~~~
-
-The ``Modeler`` module contains all properties and methods needed to edit a
-modeler, including all primitives methods and properties:
-
-
-* ``Modeler3DLayout`` for HFSS 3D Layout
-
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- modelerpcb.Modeler3DLayout
-
-
-Objects in HFSS 3D Layout
-~~~~~~~~~~~~~~~~~~~~~~~~~
-The following classes define the object properties for HFSS 3D Layout.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.pcb
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- object3dlayout.Components3DLayout
- object3dlayout.Nets3DLayout
- object3dlayout.Pins3DLayout
- object3dlayout.Line3dLayout
- object3dlayout.Polygons3DLayout
- object3dlayout.Circle3dLayout
- object3dlayout.Rect3dLayout
- object3dlayout.Points3dLayout
- object3dlayout.Padstack
-
-.. code:: python
-
- from pyaedt import Hfss3dLayout
- app = Hfss3dLayout(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Modeler3DLayout class
- modeler = app.modeler
-
- # This call returns a Primitives3D object
- primitives = modeler
-
- # This call returns an Object3d object
- my_rect = primitives.create_rectangle([0,0,0],[10,10])
-
- # Getter and setter
- my_rect.material_name
-
- ...
diff --git a/doc/source/API/PrimitivesCircuit.rst b/doc/source/API/PrimitivesCircuit.rst
deleted file mode 100644
index c6c8d185bc1..00000000000
--- a/doc/source/API/PrimitivesCircuit.rst
+++ /dev/null
@@ -1,174 +0,0 @@
-Modeler and components Circuit
-==============================
-
-This section lists the core AEDT Modeler modules:
-
-* Modeler
-* Primitives
-* Objects
-
-They are accessible through the ``modeler`` module and ``modeler.objects`` property:
-
-.. code:: python
-
-
- from pyaedt import TwinBuilder
- app = TwinBuilder(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Modeler class
- modeler = app.modeler
-
- ...
-
-
-Modeler
-~~~~~~~
-
-The ``Modeler`` module contains all properties and methods needed to edit a
-modeler, including all primitives methods and properties:
-
-* ``ModelerNexxim`` for Circuit
-* ``ModelerTwinBuilder`` for Twin Builder
-* ``ModelerEmit`` for EMIT
-
-
-.. currentmodule:: pyaedt.modeler
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- schematic.ModelerNexxim
- schematic.ModelerTwinBuilder
- schematic.ModelerEmit
- schematic.ModelerMaxwellCircuit
-
-
-Schematic in Circuit
-~~~~~~~~~~~~~~~~~~~~
-The following classes define the object properties for Circuit components.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.circuits.PrimitivesNexxim
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- NexximComponents
-
-.. code:: python
-
- from pyaedt import Circuit
- app = Circuit(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns a Schematic object
- schematic = modeler.schematic
-
- # This call returns an Object3d object
- my_res = schematic.create_resistor("R1", 50)
-
-
-Objects in Circuit
-~~~~~~~~~~~~~~~~~~
-The following classes define the object properties for Circuit.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.circuits
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- object3dcircuit.CircuitComponent
- object3dcircuit.CircuitPins
- object3dcircuit.Wire
-
-.. code:: python
-
- from pyaedt import Circuit
- app = Circuit(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Modeler class
- modeler = app.modeler
-
- # This call returns a Schematic object
- schematic = modeler.schematic
-
- # This call returns an Object3d object
- my_res = schematic.create_resistor("R1", 50)
-
- # Getter and setter
- my_res.location
- my_res.parameters["R"]=100
-
- ...
-
-Schematic in EMIT
-~~~~~~~~~~~~~~~~~
-The following classes define the object properties for EMIT components.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.circuits.PrimitivesEmit
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- EmitComponents
-
-
-Schematic in Twin Builder
-~~~~~~~~~~~~~~~~~~~~~~~~~
-The following classes define the object properties for Twin Builder components.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.circuits.PrimitivesTwinBuilder
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- TwinBuilderComponents
-
-.. code:: python
-
- from pyaedt import TwinBuilder
- app = TwinBuilder(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Modeler class
- modeler = app.modeler
-
- # This call returns a Schematic object
- schematic = modeler.schematic
-
- # This call returns an Object3d object
- my_res = schematic.create_resistor("R1", 50)
-
- # Getter and setter
- my_res.location
- my_res.parameters["R"]=100
-
- ...
-
-
-Schematic in Maxwell Circuit
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The following classes define the object properties for Maxwell Circuit components.
-They contain all getters and setters to simplify object manipulation.
-
-.. currentmodule:: pyaedt.modeler.circuits.PrimitivesMaxwellCircuit
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- MaxwellCircuitComponents
diff --git a/doc/source/API/Setup.rst b/doc/source/API/Setup.rst
deleted file mode 100644
index c2dc1654f24..00000000000
--- a/doc/source/API/Setup.rst
+++ /dev/null
@@ -1,62 +0,0 @@
-Setup
-=====
-This section lists setup modules:
-
-* ``Setup`` for HFSS, Maxwell 2D, Maxwell 3D, Q2D Extractor, and Q3D Extractor
-* ``Setup3DLayout`` for HFSS 3D Layout
-* ``SetupCircuit`` for Circuit and Twin Builder
-
-The ``Setup`` object is accessible through the ``create_setup`` method and ``setups`` object list.
-
-.. currentmodule:: pyaedt.modules.SolveSetup
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- SetupHFSS
- SetupHFSSAuto
- SetupSBR
- SetupQ3D
- SetupMaxwell
- Setup
- Setup3DLayout
- SetupCircuit
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the Setup class
- my_setup = app.setups[0]
-
-
- # This call returns a Setup object
- setup = app.create_setup("MySetup")
-
- ...
-
-
-Sweep classes
-=============
-This section lists sweep classes and their default values:
-
-* ``SweepHFSS`` for HFSS
-* ``SweepHFSS3DLayout`` for HFSS 3D Layout
-* ``SweepMatrix`` for Q3D and 2D Extractor
-
-The ``Setup`` object is accessible through the methods available for sweep creation.
-
-
-.. currentmodule:: pyaedt.modules.SolveSweeps
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- SweepHFSS
- SweepHFSS3DLayout
- SweepMatrix
diff --git a/doc/source/API/SetupTemplates.rst b/doc/source/API/SetupTemplates.rst
deleted file mode 100644
index ece5d77edb1..00000000000
--- a/doc/source/API/SetupTemplates.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-Setup templates
-===============
-
-This section lists all setup templates with their default values and keys.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- Launch AEDT 2023 R1 in non-graphical mode
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-.. toctree::
- :maxdepth: 2
-
- SetupTemplatesHFSS
- SetupTemplates3DLayout
- SetupTemplatesMaxwell
- SetupTemplatesQ3D
- SetupTemplatesIcepak
- SetupTemplatesMechanical
- SetupTemplatesCircuit
- SetupTemplatesTwinBuilder
- SetupTemplatesRmxprt
diff --git a/doc/source/API/SetupTemplates3DLayout.rst b/doc/source/API/SetupTemplates3DLayout.rst
deleted file mode 100644
index ec9befa3850..00000000000
--- a/doc/source/API/SetupTemplates3DLayout.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-HFSS 3D Layout and arguments
-============================
-
-This section lists all setup templates with their default values and keys available in HFSS 3D Layout.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- Launch AEDT 2023 R1 in non-graphical mode
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.HFSS3DLayout
diff --git a/doc/source/API/SetupTemplatesCircuit.rst b/doc/source/API/SetupTemplatesCircuit.rst
deleted file mode 100644
index 1fe1df1a41c..00000000000
--- a/doc/source/API/SetupTemplatesCircuit.rst
+++ /dev/null
@@ -1,26 +0,0 @@
-Circuit templates and arguments
-================================
-
-This section lists all setup templates with their default values and keys available in Circuit.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.NexximLNA
-.. pprint:: pyaedt.modules.SetupTemplates.NexximDC
-.. pprint:: pyaedt.modules.SetupTemplates.NexximTransient
-.. pprint:: pyaedt.modules.SetupTemplates.NexximQuickEye
-.. pprint:: pyaedt.modules.SetupTemplates.NexximVerifEye
-.. pprint:: pyaedt.modules.SetupTemplates.NexximAMI
-
diff --git a/doc/source/API/SetupTemplatesHFSS.rst b/doc/source/API/SetupTemplatesHFSS.rst
deleted file mode 100644
index ef5ede84f66..00000000000
--- a/doc/source/API/SetupTemplatesHFSS.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-HFSS templates and arguments
-============================
-
-This section lists all setup templates with their default values and keys available in HFSS.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.HFSSDrivenAuto
-.. pprint:: pyaedt.modules.SetupTemplates.HFSSDrivenDefault
-.. pprint:: pyaedt.modules.SetupTemplates.HFSSDrivenDefault
-.. pprint:: pyaedt.modules.SetupTemplates.HFSSTransient
-.. pprint:: pyaedt.modules.SetupTemplates.HFSSSBR
-
diff --git a/doc/source/API/SetupTemplatesIcepak.rst b/doc/source/API/SetupTemplatesIcepak.rst
deleted file mode 100644
index 0d3c46980c8..00000000000
--- a/doc/source/API/SetupTemplatesIcepak.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-Icepak templates and arguments
-===============================
-
-This section lists all setup templates with their default values and keys available in Icepak.
-Note that Icepak parameters contain spaces. To use them as arguments of the ``"create_setup"`` method, these
-same parameters have to be used without spaces.
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Icepak
-
- app = Icepak()
- # Any property of this setup can be found on this page.
- setup = app.create_setup(MaxIterations=5)
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.TransientFlowOnly
-.. pprint:: pyaedt.modules.SetupTemplates.TransientTemperatureOnly
-.. pprint:: pyaedt.modules.SetupTemplates.TransientTemperatureAndFlow
-.. pprint:: pyaedt.modules.SetupTemplates.SteadyFlowOnly
-.. pprint:: pyaedt.modules.SetupTemplates.SteadyTemperatureOnly
-.. pprint:: pyaedt.modules.SetupTemplates.SteadyTemperatureAndFlow
diff --git a/doc/source/API/SetupTemplatesMaxwell.rst b/doc/source/API/SetupTemplatesMaxwell.rst
deleted file mode 100644
index 6531ca1c2e9..00000000000
--- a/doc/source/API/SetupTemplatesMaxwell.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-Maxwell templates and arguments
-===============================
-
-
-This section lists all setup templates with their default values and keys available in Maxwell 2D and 3D.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Maxwell3d
-
- Maxwell3d = Maxwell3d ()
- # Any property of this setup can be found on this page.
- setup = Maxwell3d.create_setup ()
- setup.props["MaximumPasses"] = 5
- setup.update ()
-
-.. pprint:: pyaedt.modules.SetupTemplates.MaxwellTransient
-.. pprint:: pyaedt.modules.SetupTemplates.Magnetostatic
-.. pprint:: pyaedt.modules.SetupTemplates.Electrostatic
-.. pprint:: pyaedt.modules.SetupTemplates.EddyCurrent
-.. pprint:: pyaedt.modules.SetupTemplates.ElectricTransient
diff --git a/doc/source/API/SetupTemplatesMechanical.rst b/doc/source/API/SetupTemplatesMechanical.rst
deleted file mode 100644
index c636fd2676e..00000000000
--- a/doc/source/API/SetupTemplatesMechanical.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-Mechanical templates and arguments
-==================================
-
-This section lists all setup templates with their default values and keys available in Mechanical.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
-
- from pyaedt import Mechanical
-
- app = Mechanical()
- # Any property of this setup can be found on this page.
- setup = app.create_setup(MaxModes=6)
-
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.MechTerm
-.. pprint:: pyaedt.modules.SetupTemplates.MechModal
-.. pprint:: pyaedt.modules.SetupTemplates.MechStructural
-
diff --git a/doc/source/API/SetupTemplatesQ3D.rst b/doc/source/API/SetupTemplatesQ3D.rst
deleted file mode 100644
index c7221a64e3b..00000000000
--- a/doc/source/API/SetupTemplatesQ3D.rst
+++ /dev/null
@@ -1,24 +0,0 @@
-Q3D templates and arguments
-===========================
-
-
-This section lists all setup templates with their default values and keys available in Q3D and 2D Extractor.
-Note that to use nested parameters, you can set a parameter using the "__" separator as shown in the following example.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
-
- from pyaedt import Q3d
-
- app = Q3d()
- # Any property of this setup can be found on this page.
- setup = app.create_setup(AC__MaxPasses=6)
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.Matrix
-.. pprint:: pyaedt.modules.SetupTemplates.Close
-.. pprint:: pyaedt.modules.SetupTemplates.Open
-
diff --git a/doc/source/API/SetupTemplatesRmxprt.rst b/doc/source/API/SetupTemplatesRmxprt.rst
deleted file mode 100644
index 47224efea47..00000000000
--- a/doc/source/API/SetupTemplatesRmxprt.rst
+++ /dev/null
@@ -1,33 +0,0 @@
-RMXprt templates and arguments
-==============================
-
-This section lists all setup templates with their default values and keys available in RMXprt.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.GRM
-.. pprint:: pyaedt.modules.SetupTemplates.DFIG
-.. pprint:: pyaedt.modules.SetupTemplates.TPIM
-.. pprint:: pyaedt.modules.SetupTemplates.TPSM
-.. pprint:: pyaedt.modules.SetupTemplates.BLDC
-.. pprint:: pyaedt.modules.SetupTemplates.ASSM
-.. pprint:: pyaedt.modules.SetupTemplates.PMDC
-.. pprint:: pyaedt.modules.SetupTemplates.SRM
-.. pprint:: pyaedt.modules.SetupTemplates.LSSM
-.. pprint:: pyaedt.modules.SetupTemplates.UNIM
-.. pprint:: pyaedt.modules.SetupTemplates.DCM
-.. pprint:: pyaedt.modules.SetupTemplates.CPSM
-.. pprint:: pyaedt.modules.SetupTemplates.NSSM
-
diff --git a/doc/source/API/SetupTemplatesTwinBuilder.rst b/doc/source/API/SetupTemplatesTwinBuilder.rst
deleted file mode 100644
index 220bf097168..00000000000
--- a/doc/source/API/SetupTemplatesTwinBuilder.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-Twin Builder templates and arguments
-====================================
-
-
-This section lists all setup templates with their default values and keys available in Twin Builder.
-
-You can edit a setup after it is created. Here is an example:
-
-.. code:: python
-
- from pyaedt import Hfss
-
- hfss = Hfss()
- # Any property of this setup can be found on this page.
- setup = hfss.create_setup()
- setup.props["AdaptMultipleFreqs"] = True
- setup.update()
-
-
-
-.. pprint:: pyaedt.modules.SetupTemplates.TR
diff --git a/doc/source/API/Stackup3D.rst b/doc/source/API/Stackup3D.rst
deleted file mode 100644
index 178a80dbaed..00000000000
--- a/doc/source/API/Stackup3D.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-Stackup 3D components
-=====================
-This section lists ``stackup_3d`` classes for creating and editing a stackup and objects in the 3D tools.
-This consists of a set of one or more parametrized layer objects and placing lines, patches, polygons,
-and vias.
-
-
-
-.. currentmodule:: pyaedt.modeler.advanced_cad
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- stackup_3d.Stackup3D
- stackup_3d.Layer3D
- stackup_3d.Padstack
- stackup_3d.PadstackLayer
- stackup_3d.Patch
- stackup_3d.Trace
- stackup_3d.Polygon
- stackup_3d.NamedVariable
diff --git a/doc/source/API/Variables.rst b/doc/source/API/Variables.rst
deleted file mode 100644
index 8915d342f3a..00000000000
--- a/doc/source/API/Variables.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-Variable
-========
-This module provides all functionalities for creating and editing
-design and project variables in the 3D tools.
-
-.. code:: python
-
- from pyaedt import Hfss
- app = Hfss(specified_version="2023.1",
- non_graphical=False, new_desktop_session=True,
- close_on_exit=True, student_version=False)
-
- # This call returns the VariableManager class
- variable_manager = self.aedtapp._variable_manager
-
- # Set and get a variable
- app["w"] = "10mm"
- a = app["w"]
- ...
-
-
-.. currentmodule:: pyaedt.application.Variables
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- VariableManager
- Variable
- DataSet
- CSVDataset
diff --git a/doc/source/API/index.rst b/doc/source/API/index.rst
deleted file mode 100644
index 2467efda4c8..00000000000
--- a/doc/source/API/index.rst
+++ /dev/null
@@ -1,102 +0,0 @@
-========
-AEDT API
-========
-
-This section describes PyAEDT core classes, methods, and functions
-for AEDT apps and modules. Use the search feature or click links
-to view API documentation.
-The Ansys Electronics Desktop (AEDT) is a platform that enables true electronics system design.
-`AEDT `_ provides access to the Ansys gold-standard
-electro-magnetics simulation solutions such as Ansys HFSS,
-Ansys Maxwell, Ansys Q3D Extractor, Ansys Siwave, and Ansys Icepak using electrical CAD (ECAD) and
-Mechanical CAD (MCAD) workflows.
-In addition, it includes direct links to the complete Ansys portfolio of thermal, fluid,
-and Mechanical solvers for comprehensive multiphysics analysis.
-Tight integration among these solutions provides unprecedented ease of use for setup and
-faster resolution of complex simulations for design and optimization.
-
-.. image:: ../Resources/aedt_2.png
- :width: 800
- :alt: AEDT Applications
- :target: https://www.ansys.com/products/electronics
-
-The PyAEDT API includes classes for apps and modules. You must initialize the
-PyAEDT app to get access to all modules and methods. Available apps are:
-
-- `HFSS `_
-- `HFSS 3D Layout `_
-- `Maxwell 3D `_
-- `Maxwell 2D `_
-- `Maxwell Circuit `_
-- `Q3D `_
-- `Q2D Extractor `_
-- `Icepak `_
-- `Mechanical `_
-- RMXprt
-- EMIT
-- Circuit
-- `TwinBuilder `_
-
-All other classes and methods are inherited into the app class.
-The desktop app is implicitly launched in any of the other applications.
-Before accessing a PyAEDT app, the desktop app has to be launched and initialized.
-The desktop app can be explicitly or implicitly initialized as shown in the following examples.
-
-Example with ``Desktop`` class explicit initialization:
-
-.. code:: python
-
- from pyaedt import launch_desktop, Circuit
- d = launch_desktop(specified_version="2023.1",
- non_graphical=False,
- new_desktop_session=True,
- close_on_exit=True,
- student_version=False):
- circuit = Circuit()
- ...
- # Any error here should be caught by the desktop app.
- ...
- d.release_desktop()
-
-Example with ``Desktop`` class implicit initialization:
-
-.. code:: python
-
- from pyaedt import Circuit
- circuit = Circuit(specified_version="2023.1",
- non_graphical=False,
- new_desktop_session=True,
- close_on_exit=True,
- student_version=False):
- circuit = Circuit()
- ...
- # Any error here should be caught by the desktop app.
- ...
- circuit.release_desktop()
-
-
-.. toctree::
- :maxdepth: 2
-
- Application
- MaterialManagement
- Primitives3D
- Primitives2D
- Primitive_Objects
- Primitives3DLayout
- PrimitivesCircuit
- Boundaries
- Mesh
- Setup
- Post
- DesktopMessenger
- Optimetrics
- Variables
- Constants
- Configuration
- SetupTemplates
- CableModeling
-
-
-
-
diff --git a/doc/source/EDBAPI/ComponentsEdb.rst b/doc/source/EDBAPI/ComponentsEdb.rst
deleted file mode 100644
index 97a173f77d3..00000000000
--- a/doc/source/EDBAPI/ComponentsEdb.rst
+++ /dev/null
@@ -1,50 +0,0 @@
-Components
-==========
-This section contains API references for component management.
-The main component object is called directly from main application using the property ``components``.
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- pins =edb.components.get_pin_from_component("U2A5")
-
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.components
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- Components
-
-
-Instances and definitions
--------------------------
-These classes are the containers of data management for components reference designator and definitions.
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.components_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- EDBComponent
- EDBComponentDef
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- comp = edb.components["C1"]
-
- comp.is_enabled = True
- part = edb.components.definitions["AAA111"]
- ...
\ No newline at end of file
diff --git a/doc/source/EDBAPI/CoreEdb.rst b/doc/source/EDBAPI/CoreEdb.rst
deleted file mode 100644
index 0ab464e1be6..00000000000
--- a/doc/source/EDBAPI/CoreEdb.rst
+++ /dev/null
@@ -1,84 +0,0 @@
-EDB manager
-===========
-An AEDB database is a folder that contains the database representing any part of a PCB.
-It can be opened and edited using the ``Edb`` class.
-
-.. image:: ../Resources/3dlayout_1.png
- :width: 800
- :alt: HFSS 3D Layout is the tool used to visualize EDB content.
-
-
-
-.. autosummary::
- :toctree: _autosummary
-
- pyaedt.edb.Edb
- pyaedt.edb_core.edb_data.variables.Variable
- pyaedt.edb_core.edb_data.edbvalue.EdbValue
-
-
-.. code:: python
-
- from pyaedt import Edb
- # this call returns the Edb class initialized on 2023 R1
- edb = Edb(myedb, edbversion="2023.1")
-
- ...
-
-
-EDB modules
-~~~~~~~~~~~
-This section lists the core EDB modules for reading and writing information
-to AEDB files.
-
-
-.. currentmodule:: pyaedt.edb_core
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- hfss.EdbHfss
- siwave.EdbSiwave
- materials.Materials
-
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.edbvalue
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- EdbValue
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- # this call returns the EdbHfss Class
- comp = edb.hfss
-
- # this call returns the Components Class
- comp = edb.components
-
- # this call returns the EdbSiwave Class
- comp = edb.siwave
-
- # this call returns the EdbPadstacks Class
- comp = edb.padstacks
-
- # this call returns the Stackup Class
- comp = edb.stackup
-
- # this call returns the Materials Class
- comp = edb.materials
-
- # this call returns the EdbNets Class
- comp = edb.nets
-
- ...
diff --git a/doc/source/EDBAPI/LayerData.rst b/doc/source/EDBAPI/LayerData.rst
deleted file mode 100644
index 622bca08acf..00000000000
--- a/doc/source/EDBAPI/LayerData.rst
+++ /dev/null
@@ -1,37 +0,0 @@
-Stackup & layers
-================
-These classes are the containers of the layer and stackup manager of the EDB API.
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- # this call returns the EDBLayers class
- layer = edb.stackup.stackup_layers
-
- # this call returns the EDBLayer class
- layer = edb.stackup["TOP"]
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.stackup
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- Stackup
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.layer_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- LayerEdbClass
-
-
diff --git a/doc/source/EDBAPI/NetsEdb.rst b/doc/source/EDBAPI/NetsEdb.rst
deleted file mode 100644
index 52df7f43633..00000000000
--- a/doc/source/EDBAPI/NetsEdb.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-Nets
-====
-This section contains API references for net management.
-The main component object is called directly from main application using the property ``nets``.
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- edb.nets.plot(None,None)
-
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.nets
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- EdbNets
-
-
-Net properties
---------------
-The following class is the container of data management for nets, extended nets and differential pairs.
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.nets_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- EDBNetsData
- EDBNetClassData
- EDBExtendedNetData
- EDBDifferentialPairData
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- edb.nets["M_MA<6>"].delete()
- edb.net_classes
- edb.differential_pairs
- edb.extended_nets
-
-
- ...
\ No newline at end of file
diff --git a/doc/source/EDBAPI/PadstackEdb.rst b/doc/source/EDBAPI/PadstackEdb.rst
deleted file mode 100644
index 9eac145f723..00000000000
--- a/doc/source/EDBAPI/PadstackEdb.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-vias and padstacks
-==================
-This section contains API references for padstack management.
-The main padstack object is called directly from main application using the property ``padstacks``.
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- edb.padstacks.create_padstack(
- padstackname="SVIA", holediam="$via_hole_size", antipaddiam="$antipaddiam", paddiam="$paddiam"
- )
-
-
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.padstack
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- EdbPadstacks
-
-
-Instances and definitions
--------------------------
-These classes are the containers of data management for padstacks instances and padstack definitions.
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.padstacks_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- EDBPadProperties
- EDBPadstack
- EDBPadstackInstance
diff --git a/doc/source/EDBAPI/PortsEdb.rst b/doc/source/EDBAPI/PortsEdb.rst
deleted file mode 100644
index a2959237a1d..00000000000
--- a/doc/source/EDBAPI/PortsEdb.rst
+++ /dev/null
@@ -1,23 +0,0 @@
-Ports
-=====
-These classes are the containers of ports methods of the EDB for both HFSS and Siwave.
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- # this call returns the EDB excitations dictionary
- edb.ports
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.ports
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- GapPort
- WavePort
diff --git a/doc/source/EDBAPI/PrimitivesEdb.rst b/doc/source/EDBAPI/PrimitivesEdb.rst
deleted file mode 100644
index 26b73de557c..00000000000
--- a/doc/source/EDBAPI/PrimitivesEdb.rst
+++ /dev/null
@@ -1,52 +0,0 @@
-Modeler & primitives
-====================
-These classes are the containers of primitives and all relative methods.
-Primitives are planes, lines, rectangles, and circles.
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- top_layer_obj = edb.modeler.create_rectangle("TOP", net_name="gnd",
- lower_left_point=plane_lw_pt,
- upper_right_point=plane_up_pt)
-
- ...
-
-.. currentmodule:: pyaedt.edb_core.layout
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- EdbLayout
-
-
-Primitives properties
----------------------
-These classes are the containers of data management for primitives and arcs.
-
-.. currentmodule:: pyaedt.edb_core.edb_data.primitives_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- EDBPrimitives
- EDBArcs
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- polygon = edbapp.modeler.polygons[0]
- polygon.is_void
- poly2 = polygon.clone()
-
- ...
diff --git a/doc/source/EDBAPI/SiWave.rst b/doc/source/EDBAPI/SiWave.rst
deleted file mode 100644
index db813f29cb5..00000000000
--- a/doc/source/EDBAPI/SiWave.rst
+++ /dev/null
@@ -1,30 +0,0 @@
-Siwave manager
-==============
-`Siwave `_ is a specialized tool
-for power integrity, signal integrity, and EMI analysis of IC packages and PCB. This tool
-solves power delivery systems and high-speed channels in electronic devices. It can be
-accessed from PyAEDT in Windows only. All setups can be implemented through EDB API.
-
-.. image:: ../Resources/siwave.png
- :width: 800
- :alt: Siwave
- :target: https://www.ansys.com/products/electronics/ansys-siwave
-
-
-.. currentmodule:: pyaedt
-
-.. autosummary::
- :toctree: _autosummary
-
- siwave.Siwave
-
-
-.. code:: python
-
- from pyaedt.siwave import Siwave
- # this call returns the Edb class initialized on 2023 R1
- siwave = Siwave(specified_version="2023.1")
- siwave.open_project("pyproject.siw")
- siwave.export_element_data("mydata.txt")
- siwave.close_project()
- ...
\ No newline at end of file
diff --git a/doc/source/EDBAPI/SimulationConfigurationEdb.rst b/doc/source/EDBAPI/SimulationConfigurationEdb.rst
deleted file mode 100644
index 5895facc85f..00000000000
--- a/doc/source/EDBAPI/SimulationConfigurationEdb.rst
+++ /dev/null
@@ -1,40 +0,0 @@
-Simulation configuration
-========================
-These classes are the containers of simulation configuration constructors for the EDB.
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.simulation_configuration
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
- SimulationConfiguration
- SimulationConfigurationDc
- SimulationConfigurationAc
- SimulationConfigurationBatch
-
-
-
-.. code:: python
-
- from pyaedt import Edb
- edbapp = Edb(myedb, edbversion="2023.1")
-
- sim_setup = edbapp.new_simulation_configuration()
- sim_setup.solver_type = sim_setup.SOLVER_TYPE.SiwaveSYZ
- sim_setup.batch_solve_settings.cutout_subdesign_expansion = 0.01
- sim_setup.batch_solve_settings.do_cutout_subdesign = True
- sim_setup.use_default_cutout = False
- sim_setup.batch_solve_settings.signal_nets = ["PCIE0_RX0_P", "PCIE0_RX0_N", "PCIE0_TX0_P_C", "PCIE0_TX0_N_C",
- "PCIE0_TX0_P", "PCIE0_TX0_N"]
- sim_setup.batch_solve_settings.components = ["U2A5", "J2L1"]
- sim_setup.batch_solve_settings.power_nets = ["GND"]
- sim_setup.ac_settings.start_freq = "100Hz"
- sim_setup.ac_settings.stop_freq = "6GHz"
- sim_setup.ac_settings.step_freq = "10MHz"
-
- sim_setup.export_json(os.path.join(project_path, "configuration.json"))
- edbapp.build_simulation_project(sim_setup)
-
- ...
diff --git a/doc/source/EDBAPI/SimulationEdb.rst b/doc/source/EDBAPI/SimulationEdb.rst
deleted file mode 100644
index 48d3d97158a..00000000000
--- a/doc/source/EDBAPI/SimulationEdb.rst
+++ /dev/null
@@ -1,43 +0,0 @@
-Simulation setups
-=================
-These classes are the containers of ``setup`` classes in EDB for both HFSS and Siwave.
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- # this call create a setup and returns the object
- setup = edb.create_hfss_setup("my_setup")
- setup.set_solution_single_frequency()
- setup.hfss_solver_settings.enhanced_low_freq_accuracy = True
- setup.hfss_solver_settings.order_basis = "first"
-
- setup.adaptive_settings.add_adaptive_frequency_data("5GHz", 8, "0.01")
- ...
-
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
-
-
- hfss_simulation_setup_data.HfssSimulationSetup
- hfss_simulation_setup_data.EdbFrequencySweep
- hfss_simulation_setup_data.DcrSettings
- hfss_simulation_setup_data.CurveApproxSettings
- hfss_simulation_setup_data.AdvancedMeshSettings
- hfss_simulation_setup_data.ViaSettings
- hfss_simulation_setup_data.DefeatureSettings
- hfss_simulation_setup_data.AdaptiveSettings
- hfss_simulation_setup_data.AdaptiveFrequencyData
- hfss_simulation_setup_data.HfssSolverSettings
- hfss_simulation_setup_data.HfssPortSettings
- hfss_simulation_setup_data.MeshOperationLength
- hfss_simulation_setup_data.MeshOperationSkinDepth
- siwave_simulation_setup_data.SiwaveSYZSimulationSetup
- siwave_simulation_setup_data.SiwaveDCSimulationSetup
diff --git a/doc/source/EDBAPI/SourcesEdb.rst b/doc/source/EDBAPI/SourcesEdb.rst
deleted file mode 100644
index 59302352af3..00000000000
--- a/doc/source/EDBAPI/SourcesEdb.rst
+++ /dev/null
@@ -1,20 +0,0 @@
-Sources and excitations
-=======================
-These classes are the containers of sources methods of the EDB for both HFSS and Siwave.
-
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb(myedb, edbversion="2023.1")
-
- # this call returns the EDB excitations dictionary
- edb.excitations
- ...
-
-
-.. currentmodule:: pyaedt.edb_core.edb_data.sources
-
-.. autosummary::
- :toctree: _autosummary
- :nosignatures:
diff --git a/doc/source/EDBAPI/index.rst b/doc/source/EDBAPI/index.rst
deleted file mode 100644
index 14e1abb5707..00000000000
--- a/doc/source/EDBAPI/index.rst
+++ /dev/null
@@ -1,43 +0,0 @@
-=======
-EDB API
-=======
-
-This section describes PyAEDT EDB classes, methods, and functions
-for EDB apps and modules. Use the search feature or click links
-to view API documentation.
-
-The PyAEDT EDB API includes classes for apps and modules. You must initialize the
-EDB class to get access to all modules and methods.
-All other classes and methods are inherited into the app class.
-If EDB is launched within the ``HfssdLayout`` class, EDB is accessible in read-only mode.
-
-
-.. image:: ../Resources/edb_intro.png
- :width: 800
- :alt: EDB Applications
- :target: https://www.ansys.com/applications/pcbs-ics-ic-packages
-
-
-Example:
-
-.. code:: python
-
- from pyaedt import Edb
- edb = Edb("my_project.aedb", edbversion="2023.1")
- edb.core_components.components["R1"].r_value = 40
- edb.close_edb()
-
-
-.. toctree::
- :maxdepth: 2
-
- CoreEdb
- LayerData
- PrimitivesEdb
- ComponentsEdb
- NetsEdb
- PadstackEdb
- SourcesEdb
- SimulationEdb
- SimulationConfigurationEdb
- SiWave
\ No newline at end of file
diff --git a/doc/source/User_guide/pyaedt_file_data/project.rst b/doc/source/User_guide/pyaedt_file_data/project.rst
index d9b965f0de1..9f716d74373 100644
--- a/doc/source/User_guide/pyaedt_file_data/project.rst
+++ b/doc/source/User_guide/pyaedt_file_data/project.rst
@@ -33,7 +33,7 @@ File structure examples:
:download:`HFSS 3D Layout Example <../../Resources/hfss3dlayout_project_example.json>`
-.. code-block:: json
+.. code-block::
{
"general": {
diff --git a/doc/source/_static/custom.css b/doc/source/_static/css/custom.css
similarity index 100%
rename from doc/source/_static/custom.css
rename to doc/source/_static/css/custom.css
diff --git a/doc/source/_static/css/highlight.css b/doc/source/_static/css/highlight.css
new file mode 100644
index 00000000000..f2ca46252fc
--- /dev/null
+++ b/doc/source/_static/css/highlight.css
@@ -0,0 +1,83 @@
+/*
+ * The 'friendly' style from Pygments CSS style. Directly taken from:
+ * https://github.com/richleland/pygments-css
+ * License is 'UNLICENSE.txt'.
+ */
+
+@import "../../ansys-sphinx-theme.css";
+
+/* Do not show number cells */
+.nbinput .prompt,
+.nboutput .prompt {
+ display: none;
+}
+
+.highlight .hll { background-color: #ffffcc !important; }
+.highlight { font-size: 1rem; background: #f0f0f0 !important; }
+.highlight .c { color: #60a0b0 !important; font-style: italic !important; } /* Comment */
+.highlight .err { border: 1px solid #FF0000 !important; } /* Error */
+.highlight .k { color: #007020 !important; font-weight: bold !important; } /* Keyword */
+.highlight .o { color: #666666 !important; } /* Operator */
+.highlight .ch { color: #60a0b0 !important; font-style: italic !important; } /* Comment.Hashbang */
+.highlight .cm { color: #60a0b0 !important; font-style: italic !important; } /* Comment.Multiline */
+.highlight .cp { color: #007020 !important; } /* Comment.Preproc */
+.highlight .cpf { color: #60a0b0 !important; font-style: italic !important; } /* Comment.PreprocFile */
+.highlight .c1 { color: #60a0b0 !important; font-style: italic !important; } /* Comment.Single */
+.highlight .cs { color: #60a0b0 !important; background-color: #fff0f0 !important; } /* Comment.Special */
+.highlight .gd { color: #A00000 !important; } /* Generic.Deleted */
+.highlight .ge { font-style: italic !important; } /* Generic.Emph */
+.highlight .gr { color: #FF0000 !important; } /* Generic.Error */
+.highlight .gh { color: #000080 !important; font-weight: bold !important; } /* Generic.Heading */
+.highlight .gi { color: #00A000 !important; } /* Generic.Inserted */
+.highlight .go { color: #888888 !important; } /* Generic.Output */
+.highlight .gp { color: #c65d09 !important; font-weight: bold !important; } /* Generic.Prompt */
+.highlight .gs { font-weight: bold !important; } /* Generic.Strong */
+.highlight .gu { color: #800080 !important; font-weight: bold !important; } /* Generic.Subheading */
+.highlight .gt { color: #0044DD !important; } /* Generic.Traceback */
+.highlight .kc { color: #007020 !important; font-weight: bold !important; } /* Keyword.Constant */
+.highlight .kd { color: #007020 !important; font-weight: bold !important; } /* Keyword.Declaration */
+.highlight .kn { color: #007020 !important; font-weight: bold !important; } /* Keyword.Namespace */
+.highlight .kp { color: #007020 !important; } /* Keyword.Pseudo */
+.highlight .kr { color: #007020 !important; font-weight: bold !important; } /* Keyword.Reserved */
+.highlight .kt { color: #902000 !important; } /* Keyword.Type */
+.highlight .m { color: #40a070 !important; } /* Literal.Number */
+.highlight .s { color: #4070a0 !important; } /* Literal.String */
+.highlight .na { color: #4070a0 !important; } /* Name.Attribute */
+.highlight .nb { color: #007020 !important; } /* Name.Builtin */
+.highlight .nc { color: #0e84b5 !important; font-weight: bold !important; } /* Name.Class */
+.highlight .no { color: #60add5 !important; } /* Name.Constant */
+.highlight .nd { color: #555555 !important; font-weight: bold !important; } /* Name.Decorator */
+.highlight .ni { color: #d55537 !important; font-weight: bold !important; } /* Name.Entity */
+.highlight .ne { color: #007020 !important; } /* Name.Exception */
+.highlight .nf { color: #06287e !important; } /* Name.Function */
+.highlight .nl { color: #002070 !important; font-weight: bold !important; } /* Name.Label */
+.highlight .nn { color: #0e84b5 !important; font-weight: bold !important; } /* Name.Namespace */
+.highlight .nt { color: #062873 !important; font-weight: bold !important; } /* Name.Tag */
+.highlight .nv { color: #bb60d5 !important; } /* Name.Variable */
+.highlight .ow { color: #007020 !important; font-weight: bold !important; } /* Operator.Word */
+.highlight .w { color: #bbbbbb !important; } /* Text.Whitespace */
+.highlight .mb { color: #40a070 !important; } /* Literal.Number.Bin */
+.highlight .mf { color: #40a070 !important; } /* Literal.Number.Float */
+.highlight .mh { color: #40a070 !important; } /* Literal.Number.Hex */
+.highlight .mi { color: #40a070 !important; } /* Literal.Number.Integer */
+.highlight .mo { color: #40a070 !important; } /* Literal.Number.Oct */
+.highlight .sa { color: #4070a0 !important; } /* Literal.String.Affix */
+.highlight .sb { color: #4070a0 !important; } /* Literal.String.Backtick */
+.highlight .sc { color: #4070a0 !important; } /* Literal.String.Char */
+.highlight .dl { color: #4070a0 !important; } /* Literal.String.Delimiter */
+.highlight .sd { color: #4070a0 !important; font-style: italic !important; } /* Literal.String.Doc */
+.highlight .s2 { color: #4070a0 !important; } /* Literal.String.Double */
+.highlight .se { color: #4070a0 !important; font-weight: bold !important; } /* Literal.String.Escape */
+.highlight .sh { color: #4070a0 !important; } /* Literal.String.Heredoc */
+.highlight .si { color: #70a0d0 !important; font-style: italic !important; } /* Literal.String.Interpol */
+.highlight .sx { color: #c65d09 !important; } /* Literal.String.Other */
+.highlight .sr { color: #235388 !important; } /* Literal.String.Regex */
+.highlight .s1 { color: #4070a0 !important; } /* Literal.String.Single */
+.highlight .ss { color: #517918 !important; } /* Literal.String.Symbol */
+.highlight .bp { color: #007020 !important; } /* Name.Builtin.Pseudo */
+.highlight .fm { color: #06287e !important; } /* Name.Function.Magic */
+.highlight .vc { color: #bb60d5 !important; } /* Name.Variable.Class */
+.highlight .vg { color: #bb60d5 !important; } /* Name.Variable.Global */
+.highlight .vi { color: #bb60d5 !important; } /* Name.Variable.Instance */
+.highlight .vm { color: #bb60d5 !important; } /* Name.Variable.Magic */
+.highlight .il { color: #40a070 !important; } /* Literal.Number.Integer.Long */
diff --git a/doc/source/_static/diff_via.png b/doc/source/_static/thumbnails/diff_via.png
similarity index 100%
rename from doc/source/_static/diff_via.png
rename to doc/source/_static/thumbnails/diff_via.png
diff --git a/doc/source/conf.py b/doc/source/conf.py
index a072c1cf724..d9f3a523d89 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -3,14 +3,16 @@
# -- Project information -----------------------------------------------------
import datetime
import os
+import re
import pathlib
import sys
import warnings
+from sphinx.util import logging
import pyvista
import numpy as np
import json
-from sphinx_gallery.sorting import FileNameSortKey
+# from sphinx_gallery.sorting import FileNameSortKey
from ansys_sphinx_theme import (ansys_favicon,
get_version_match, pyansys_logo_black,
watermark,
@@ -42,6 +44,11 @@ def visit_desc_content(self, node: Element) -> None:
# <----------------- End of sphinx pdf builder override---------------->
+logger = logging.getLogger(__name__)
+
+path = pathlib.Path(__file__).parent.parent.parent / "examples"
+EXAMPLES_DIRECTORY = path.resolve()
+
class PrettyPrintDirective(Directive):
"""Renders a constant using ``pprint.pformat`` and inserts into the document."""
required_arguments = 1
@@ -60,6 +67,18 @@ def run(self):
addnodes.desc_content('', literal)
]
+# Sphinx event hooks
+
+def directory_size(directory_path):
+ """Compute the size (in mega bytes) of a directory."""
+ res = 0
+ for path, _, files in os.walk(directory_path):
+ for f in files:
+ fp = os.path.join(path, f)
+ res += os.stat(fp).st_size
+ # Convert in mega bytes
+ res /= 1e6
+ return res
def autodoc_skip_member(app, what, name, obj, skip, options):
try:
@@ -70,18 +89,160 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
return True if (skip or exclude or exclude2) else None # Can interfere with subsequent skip functions.
# return True if exclude else None
-
def remove_doctree(app, exception):
"""Remove the .doctree directory created during the documentation build.
"""
- shutil.rmtree(app.doctreedir)
+ size = directory_size(app.doctreedir)
+ logger.info(f"Removing doctree {app.doctreedir} ({size} MB).")
+ shutil.rmtree(app.doctreedir, ignore_errors=True)
+ logger.info(f"Doctree removed.")
+
+def copy_examples(app):
+ """Copy directory examples (root directory) files into the doc/source/examples directory.
+ """
+ DESTINATION_DIRECTORY = pathlib.Path(app.srcdir, "examples").resolve()
+ logger.info(f"Copying examples from {EXAMPLES_DIRECTORY} to {DESTINATION_DIRECTORY}.")
+ if os.path.exists(DESTINATION_DIRECTORY):
+ size = directory_size(DESTINATION_DIRECTORY)
+ logger.info(f"Directory {DESTINATION_DIRECTORY} ({size} MB) already exist, removing it.")
+ shutil.rmtree(DESTINATION_DIRECTORY)
+ logger.info(f"Directory removed.")
+
+ shutil.copytree(EXAMPLES_DIRECTORY, DESTINATION_DIRECTORY)
+ logger.info(f"Copy performed")
+
+def remove_examples(app, exception):
+ """Remove the doc/source/examples directory created during the documentation build.
+ """
+ DESTINATION_DIRECTORY = pathlib.Path(app.srcdir) / "examples"
+ size = directory_size(DESTINATION_DIRECTORY)
+ logger.info(f"Removing directory {DESTINATION_DIRECTORY} ({size} MB).")
+ shutil.rmtree(DESTINATION_DIRECTORY, ignore_errors=True)
+ logger.info(f"Directory removed.")
+
+def add_ipython_time(app, docname, source):
+ """Add '# %%time' to every code cell in an example Python script.
+ """
+ # Get the full path to the document
+ docpath = os.path.join(app.srcdir, docname)
+
+ # Check if this is a .py example file
+ if not os.path.exists(docpath + '.py') or not docname.startswith("examples"):
+ return
+
+ logger.info(f"Adding '# %%time' to file {docname}.py")
+ lines = source[0].split("\n")
+ modified_lines = []
+ in_code_cell = False
+ in_code_cell_plus = False
+
+ for line in lines:
+ stripped_line = line.strip()
+ # Detect the start of a new code cell
+ if stripped_line.startswith('# +'):
+ in_code_cell = True
+ in_code_cell_plus = True
+ modified_lines.append(line)
+ modified_lines.append('# %%time')
+ # Detect the end of a code cell
+ elif stripped_line.startswith('# -'):
+ in_code_cell = False
+ in_code_cell_plus = False
+ modified_lines.append(line)
+ # Detect already being in a code cell
+ elif in_code_cell and in_code_cell_plus:
+ modified_lines.append(line)
+ elif in_code_cell and not in_code_cell_plus:
+ # Detect being out of a code cell
+ if stripped_line == "":
+ in_code_cell = False
+ modified_lines.append(line)
+ elif not in_code_cell:
+ # Detect the start of a new code cell
+ if not stripped_line.startswith("# ") and stripped_line not in ("", "#"):
+ in_code_cell = True
+ modified_lines.append('# %%time')
+ modified_lines.append(line)
+ # Detect already being out of a code cell
+ else:
+ modified_lines.append(line)
+ else:
+ raise Exception("not handled")
+
+ # Update the source
+ source[0] = "\n".join(modified_lines)
+ # logger.info(source[0])
+
+def adjust_image_path(app, docname, source):
+ """Adjust the HTML label used to insert images in the examples.
+
+ The following path makes the examples in the root directory work:
+ #
+ However, examples fail when used through the documentation build because
+ reaching the associated path should be "../../_static/diff_via.png".
+ Indeed, the directory ``_static`` is automatically copied into the output directory
+ ``_build/html/_static``.
+ """
+ # Get the full path to the document
+ docpath = os.path.join(app.srcdir, docname)
+
+ # Check if this is a PY example file
+ if not os.path.exists(docpath + '.py') or not docname.startswith("examples"):
+ return
+
+ logger.info(f"Changing HTML image path in '{docname}.py' file.")
+ source[0] = source[0].replace('../../doc/source/_static', '../../_static')
+
+def remove_ipython_time_from_html(app, pagename, templatename, context, doctree):
+ """Remove '# %%time' from examples generated HTML files.
+ """
+ if pagename.startswith("examples") and not pagename.endswith("/index"):
+ logger.info(f"Removing '# %%time' from file {pagename}")
+ pattern = r'%%time<\/span>\n'
+ context['body'] = re.sub(pattern, '', context['body'])
+
+def check_example_error(app, pagename, templatename, context, doctree):
+ """Log an error if the execution of an example as a notebook triggered an error.
+
+ Since the documentation build might not stop if the execution of a notebook triggered
+ an error, we use a flag to log that an error is spotted in the html page context.
+ """
+ # Check if the HTML contains an error message
+ if pagename.startswith("examples") and not pagename.endswith("/index"):
+ if any(map(lambda msg: msg in context['body'], ['UsageError', 'NameError'])):
+ logger.error(f"An error was detected in file {pagename}")
+ app.builder.config.html_context['build_error'] = True
+
+def check_build_finished_without_error(app, exception):
+ """Check that no error is detected along the documentation build process."""
+ if app.builder.config.html_context.get('build_error', False):
+ raise Exception('Build failed due to error in html-page-context')
+
+def check_pandoc_installed(app):
+ """Ensure that pandoc is installed
+ """
+ import pypandoc
+ try:
+ pandoc_path = pypandoc.get_pandoc_path()
+ pandoc_dir = os.path.dirname(pandoc_path)
+ if pandoc_dir not in os.environ["PATH"].split(os.pathsep):
+ os.environ["PATH"] += os.pathsep + pandoc_dir
+ except OSError:
+ logger.error("Pandoc was not found, please add it to your path or install pypandoc-binary")
def setup(app):
app.add_directive('pprint', PrettyPrintDirective)
app.connect('autodoc-skip-member', autodoc_skip_member)
+ app.connect('builder-inited', copy_examples)
+ app.connect("builder-inited", check_pandoc_installed)
+ app.connect('source-read', add_ipython_time)
+ app.connect('source-read', adjust_image_path)
+ app.connect('html-page-context', remove_ipython_time_from_html)
+ app.connect('html-page-context', check_example_error)
+ app.connect('build-finished', remove_examples)
app.connect('build-finished', remove_doctree)
-
+ app.connect('build-finished', check_build_finished_without_error)
local_path = os.path.dirname(os.path.realpath(__file__))
module_path = pathlib.Path(local_path)
@@ -120,6 +281,9 @@ def setup(app):
# extensions coming with Sphinx_PyAEDT (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
+ "sphinx.ext.graphviz",
+ "sphinx.ext.mathjax",
+ "sphinx.ext.inheritance_diagram",
"sphinx.ext.intersphinx",
"sphinx.ext.autodoc",
"sphinx.ext.todo",
@@ -129,14 +293,16 @@ def setup(app):
"sphinx_copybutton",
"sphinx_design",
"sphinx_jinja",
+ "nbsphinx",
"recommonmark",
- "sphinx.ext.graphviz",
- "sphinx.ext.mathjax",
- "sphinx.ext.inheritance_diagram",
"numpydoc",
"ansys_sphinx_theme.extension.linkcode",
+ # "myst_parser"
]
+# MathJax config
+# myst_update_mathjax = False
+
# Intersphinx mapping
intersphinx_mapping = {
"python": ("https://docs.python.org/3.11", None),
@@ -212,7 +378,7 @@ def setup(app):
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ["_build", "sphinx_boogergreen_theme_1", "Thumbs.db", ".DS_Store", "*.txt"]
+exclude_patterns = ["_build", "sphinx_boogergreen_theme_1", "Thumbs.db", ".DS_Store", "*.txt", "conf.py", "Resources/PyAEDTInstallerFromDesktop.py"]
inheritance_graph_attrs = dict(rankdir="RL", size='"8.0, 10.0"', fontsize=14, ratio="compress")
inheritance_node_attrs = dict(shape="ellipse", fontsize=14, height=0.75, color="dodgerblue1", style="filled")
@@ -236,6 +402,22 @@ def setup(app):
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
+# Execute notebooks before convertion
+nbsphinx_execute = "always"
+
+# Allow errors to help debug.
+nbsphinx_allow_errors = False
+
+# Sphinx gallery customization
+
+nbsphinx_thumbnails = {
+ "examples/00-EDB/00_EDB_Create_VIA": "_static/thumbnails/diff_via.png",
+}
+
+nbsphinx_custom_formats = {
+ # ".py": ["jupytext.reads", {"fmt": "", "cell_metadata_filter": "ExecuteTime"}],
+ ".py": ["jupytext.reads", {"fmt": ""}],
+}
# Manage errors
pyvista.set_error_output_file("errors.txt")
@@ -267,33 +449,33 @@ def setup(app):
# necessary for pyvista when building the sphinx gallery
pyvista.BUILDING_GALLERY = True
- if config["run_examples"]:
- extensions.append("sphinx_gallery.gen_gallery")
-
- sphinx_gallery_conf = {
- # convert rst to md for ipynb
- "pypandoc": True,
- # path to your examples scripts
- "examples_dirs": ["../../examples/"],
- # path where to save gallery generated examples
- "gallery_dirs": ["examples"],
- # Pattern to search for examples files
- "filename_pattern": r"\.py",
- # Remove the "Download all examples" button from the top level gallery
- "download_all_examples": False,
- # Sort gallery examples by file name instead of number of lines (default)
- "within_subsection_order": FileNameSortKey,
- # directory where function granular galleries are stored
- "backreferences_dir": None,
- # Modules for which function level galleries are created. In
- "doc_module": "ansys-pyaedt",
- "image_scrapers": ("pyvista", "matplotlib"),
- "ignore_pattern": "flycheck*",
- "thumbnail_size": (350, 350),
- # 'first_notebook_cell': ("%matplotlib inline\n"
- # "from pyvista import set_plot_theme\n"
- # "set_plot_theme('document')"),
- }
+ # if config["run_examples"]:
+ # extensions.append("sphinx_gallery.gen_gallery")
+
+ # sphinx_gallery_conf = {
+ # # convert rst to md for ipynb
+ # "pypandoc": True,
+ # # path to your examples scripts
+ # "examples_dirs": ["../../examples/"],
+ # # path where to save gallery generated examples
+ # "gallery_dirs": ["examples"],
+ # # Pattern to search for examples files
+ # "filename_pattern": r"\.py",
+ # # Remove the "Download all examples" button from the top level gallery
+ # "download_all_examples": False,
+ # # Sort gallery examples by file name instead of number of lines (default)
+ # "within_subsection_order": FileNameSortKey,
+ # # directory where function granular galleries are stored
+ # "backreferences_dir": None,
+ # # Modules for which function level galleries are created. In
+ # "doc_module": "ansys-pyaedt",
+ # "image_scrapers": ("pyvista", "matplotlib"),
+ # "ignore_pattern": "flycheck*",
+ # "thumbnail_size": (350, 350),
+ # # 'first_notebook_cell': ("%matplotlib inline\n"
+ # # "from pyvista import set_plot_theme\n"
+ # # "set_plot_theme('document')"),
+ # }
jinja_contexts = {
"main_toctree": {
@@ -362,7 +544,8 @@ def setup(app):
# These paths are either relative to html_static_path
# or fully qualified paths (eg. https://...)
html_css_files = [
- 'custom.css',
+ 'css/custom.css',
+ 'css/highlight.css',
]
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 2627b82d9df..ab37db21d1c 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -18,28 +18,6 @@ enabling straightforward and efficient automation in your workflow.
New to PyAEDT? This section provides the information that you need to get started with PyAEDT.
- .. grid-item-card:: User guide :fa:`book-open-reader`
- :link: User_guide/index
- :link-type: doc
-
- This section provides in-depth information on PyAEDT key concepts.
-
-.. grid:: 2
-
- .. grid-item-card:: AEDT API reference :fa:`book-bookmark`
- :link: API/index
- :link-type: doc
-
- This section contains descriptions of the functions and modules included in PyAEDT.
- It describes how the methods work and the parameter that can be used.
-
- .. grid-item-card:: EDB API reference :fa:`book-bookmark`
- :link: EDBAPI/index.
- :link-type: doc
-
- Contains descriptions of the functions and modules included in PyEDB.
- It describes how the methods work and the parameter that can be used.
-
.. jinja:: main_toctree
.. grid:: 2
@@ -64,10 +42,7 @@ enabling straightforward and efficient automation in your workflow.
.. toctree::
:hidden:
- Getting_started/index
User_guide/index
- API/index
- EDBAPI/index
{% if run_examples %}
examples/index
{% endif %}
diff --git a/examples/00-EDB/00_EDB_Create_VIA.py b/examples/00-EDB/00_EDB_Create_VIA.py
index 4ddbb65ba5d..71421ff955b 100644
--- a/examples/00-EDB/00_EDB_Create_VIA.py
+++ b/examples/00-EDB/00_EDB_Create_VIA.py
@@ -1,63 +1,45 @@
-"""
-EDB: geometry creation
-----------------------
-This example shows how you can use EDB to create a layout.
-"""
-######################################################################
-# Final expected project
-# ~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: geometry creation
+
+# This example shows how you can use EDB to create a layout.
+# ## Final expected project
+#
+#
#
-# .. image:: ../../_static/diff_via.png
-# :width: 600
-# :alt: Differential Vias.
-######################################################################
-
-######################################################################
-# Import EDB layout object
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import EDB layout object
# Import the EDB layout object and initialize it on version 2023 R2.
-######################################################################
+# +
import time
import os
import pyaedt
+import tempfile
-start = time.time()
-
-aedb_path = os.path.join(pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("pcb") + ".aedb")
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+aedb_path = os.path.join(temp_dir.name, "create_via.aedb")
print(aedb_path)
edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
+# -
-####################
-# Add stackup layers
-# ~~~~~~~~~~~~~~~~~~
+# ## Add stackup layers
# Add stackup layers.
-# A stackup can be created layer by layer or imported from a csv file or xml file.
-#
+# A stackup can be created layer by layer or imported from a CSV file or XML file.
edb.stackup.add_layer("GND")
edb.stackup.add_layer("Diel", "GND", layer_type="dielectric", thickness="0.1mm", material="FR4_epoxy")
edb.stackup.add_layer("TOP", "Diel", thickness="0.05mm")
-#####################################
-# Create signal net and ground planes
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create signal net and ground planes
# Create a signal net and ground planes.
-points = [
- [0.0, 0],
- [100e-3, 0.0],
-]
+points = [[0.0, 0], [100e-3, 0.0]]
edb.modeler.create_trace(points, "TOP", width=1e-3)
points = [[0.0, 1e-3], [0.0, 10e-3], [100e-3, 10e-3], [100e-3, 1e-3], [0.0, 1e-3]]
edb.modeler.create_polygon(points, "TOP")
-
points = [[0.0, -1e-3], [0.0, -10e-3], [100e-3, -10e-3], [100e-3, -1e-3], [0.0, -1e-3]]
edb.modeler.create_polygon(points, "TOP")
-#######################################
-# Create vias with parametric positions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Create vias with parametric positions
# Create vias with parametric positions.
edb.padstacks.create("MyVia")
@@ -71,27 +53,24 @@
edb.padstacks.place([45e-3, -5e-3], "MyVia")
-#######################################
-# Geometry Plot
-# ~~~~~~~~~~~~~
-#
+# ## Generate geometry plot
+
edb.nets.plot(None, color_by_net=True)
-#######################################
-# Stackup Plot
-# ~~~~~~~~~~~~
-#
-edb.stackup.plot(plot_definitions="MyVia")
+# ## Generate stackup plot
+edb.stackup.plot(plot_definitions="MyVia")
-####################
-# Save and close EDB
-# ~~~~~~~~~~~~~~~~~~
+# ## Save and close EDB
# Save and close EDB.
if edb:
edb.save_edb()
edb.close_edb()
print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path))
-end = time.time() - start
-print(end)
+
+# ### Clean up temporary directory
+#
+# The following command removes the project and the temporary directory. If you'd like to save this project, save it to a folder of your choice prior to running the following cell.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/01_edb_example.py b/examples/00-EDB/01_edb_example.py
index 62c016f2c29..0df5a65c8ea 100644
--- a/examples/00-EDB/01_edb_example.py
+++ b/examples/00-EDB/01_edb_example.py
@@ -1,127 +1,153 @@
-"""
-EDB: Siwave analysis from EDB setup
------------------------------------
-This example shows how you can use EDB to interact with a layout.
-"""
-###############################################################################
+# # EDB: SIwave DC-IR Analysis
+#
+# This example demonstrates the use of EDB to interact with a PCB
+# layout and run DC-IR analysis in SIwave.
# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+# +
import os
import time
import pyaedt
+import tempfile
-temp_folder = pyaedt.generate_unique_folder_name()
-targetfile = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_folder)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+targetfile = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',
+ destination=temp_dir.name)
siwave_file = os.path.join(os.path.dirname(targetfile), "ANSYS-HSD_V1.siw")
print(targetfile)
aedt_file = targetfile[:-4] + "aedt"
+# -
+# ## Launch Ansys Electronics Database (EDB)
+#
+# Instantiate an instance of the `pyaedt.Edb` class
+# using EDB 2023 R2 and SI units.
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
-# Launch the :class:`pyaedt.Edb` class, using EDB 2023 R2 and SI units.
edb_version = "2023.2"
if os.path.exists(aedt_file):
os.remove(aedt_file)
edb = pyaedt.Edb(edbpath=targetfile, edbversion=edb_version)
-###############################################################################
-# Compute nets and components
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Computes nets and components.
-# There are queries for nets, stackups, layers, components, and geometries.
+# ## Identify nets and components
+#
+# The ``Edb.nets.netlist`` and ``Edb.components.components`` properties contain information
+# about all of the nets and components. The following cell uses this information to print the number of nets and
+# components.
print("Nets {}".format(len(edb.nets.netlist)))
start = time.time()
print("Components {}".format(len(edb.components.components.keys())))
print("elapsed time = ", time.time() - start)
-###############################################################################
-# Get pin position
-# ~~~~~~~~~~~~~~~~
-# Get the position for a specific pin.
-# The next section shows how to get all pins for a specific component and
-# the positions of each of them.
-# Each pin is a list of ``[X, Y]`` coordinate positions.
+# ## Identify pin positions
+#
+# This code shows how to obtain all pins for a specific component and
+# print the ``[x, y]`` position of each pin.
pins = edb.components["U2"].pins
+count = 0
for pin in edb.components["U2"].pins.values():
- print(pin.position)
-
-###############################################################################
-# Get all nets connected to a component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Get all nets connected to a specific component.
-
-edb.components.get_component_net_connection_info("U2")
-
-###############################################################################
-# Compute rats
-# ~~~~~~~~~~~~
-# Computes rats.
+ if count < 10: # Only print the first 10 pin coordinates.
+ print(pin.position)
+ elif count == 10:
+ print("...and many more.")
+ else:
+ pass
+ count += 1
+
+# Get all nets connected to a specific component. Print
+# the pin and the name of the net that it is connected to.
+
+connections = edb.components.get_component_net_connection_info("U2")
+n_print = 0 # Counter to limit the number of printed lines.
+print_max = 15
+for m in range(len(connections["pin_name"])):
+ ref_des = connections["refdes"][m]
+ pin_name = connections["pin_name"][m]
+ net_name = connections["net_name"][m]
+ if net_name != "" and (n_print < print_max):
+ print("{}, pin {} -> net \"{}\"".format(ref_des, pin_name, net_name))
+ n_print += 1
+ elif n_print == print_max:
+ print("...and many more.")
+ n_print += 1
+
+# Compute rats.
rats = edb.components.get_rats()
-###############################################################################
-# Get all DC-connected net lists through inductance
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Get all DC-connected net lists through inductance.
-# The inputs needed are ground net lists. The returned list contains all nets
-# connected to a ground through an inductor.
+# ## Identify connected nets
+#
+# The ``get_dcconnected_net_list()`` method retrieves a list of
+# all DC-connected power nets. Each group of connected nets is returned
+# as a [set](https://docs.python.org/3/tutorial/datastructures.html#sets).
+# The first argument to the method is the list of ground nets, which are
+# not considered in the search for connected nets.
GROUND_NETS = ["GND", "GND_DP"]
dc_connected_net_list = edb.nets.get_dcconnected_net_list(GROUND_NETS)
-print(dc_connected_net_list)
+for pnets in dc_connected_net_list:
+ print(pnets)
-###############################################################################
-# Get power tree based on a specific net
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Get the power tree based on a specific net.
+# ## Power Tree
+#
+# The power tree provides connectivity through all components from the VRM to
+# the device.
VRM = "U1"
OUTPUT_NET = "AVCC_1V3"
powertree_df, component_list_columns, net_group = edb.nets.get_powertree(OUTPUT_NET, GROUND_NETS)
-for el in powertree_df:
- print(el)
-###############################################################################
-# Delete all RLCs with only one pin
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Delete all RLCs with only one pin. This method provides a useful way of
-# removing components not needed in the simulation.
+# Print some information about the power tree.
+
+print_columns = ["refdes", "pin_name", "component_partname"]
+ncol = [component_list_columns.index(c) for c in print_columns]
+
+# This prints the header. Replace "pin_name" with "pin" to
+# make the header align with the values.
+
+# +
+print("\t".join(print_columns).replace("pin_name", "pin"))
+
+for el in powertree_df:
+ s = ""
+ count = 0
+ for e in el:
+ if count in ncol:
+ s += "{}\t".format(e)
+ count += 1
+ s.rstrip()
+ print(s)
+# -
+
+# ## Remove unused components
+#
+# Delete all RLC components that are connected with only one pin.
+# The ``Edb.components.delete_single_pin_rlc()`` method
+# provides a useful way to
+# remove components that are not needed for the simulation.
edb.components.delete_single_pin_rlc()
-###############################################################################
-# Delete components
-# ~~~~~~~~~~~~~~~~~
-# Delete manually one or more components.
+# You can also remove unused components explicitly by name.
edb.components.delete("C380")
-###############################################################################
-# Delete nets
-# ~~~~~~~~~~~
-# Delete manually one or more nets.
+# Nets can also be removed explicitly.
edb.nets.delete("PDEN")
-###############################################################################
-# Get stackup limits
-# ~~~~~~~~~~~~~~~~~~
-# Get the stackup limits (top and bottom layers and elevations).
-
-print(edb.stackup.limits())
+# Print the top and bottom elevation of the stackup obtained using
+# the ``Edb.stackup.limits()`` method.
+s = "Top layer name: \"{top}\", Elevation: {top_el:.2f} "
+s += "mm\nBottom layer name: \"{bot}\", Elevation: {bot_el:2f} mm"
+top, top_el, bot, bot_el = edb.stackup.limits()
+print(s.format(top = top, top_el = top_el*1E3, bot = bot, bot_el = bot_el*1E3))
-
-###############################################################################
-# Create voltage source and Siwave DCIR analysis
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set up for SIwave DCIR analysis
+#
# Create a voltage source and then set up a DCIR analysis.
edb.siwave.create_voltage_source_on_net("U1", "AVCC_1V3", "U1", "GND", 1.3, 0, "V1")
@@ -131,41 +157,41 @@
setup.set_dc_slider = 0
setup.add_source_terminal_to_ground("V1", 1)
-
-
-###############################################################################
-# Save modifications
-# ~~~~~~~~~~~~~~~~~~
-# Save modifications.
+# ## Solve
+#
+# Save the modifications and run the analysis in SIwave.
edb.save_edb()
edb.nets.plot(None, "1_Top",plot_components_on_top=True)
siw_file = edb.solve_siwave()
-###############################################################################
-# Export Siwave Reports
-# ~~~~~~~~~~~~~~~~~~~~~
-# Export all DC Reports quantities.
+# ## Export results
+#
+# Export all quantities calculated from the DC-IR analysis. The following method runs SIwave in batch mode from
+# the command line. Results are written to the edb folder.
+
outputs = edb.export_siwave_dc_results(siw_file, setup.name, )
-###############################################################################
-# Close EDB
-# ~~~~~~~~~
# Close EDB. After EDB is closed, it can be opened by AEDT.
edb.close_edb()
-###############################################################################
-# Postprocess in Siwave
-# ~~~~~~~~~~~~~~~~~~~~~
-# Open Siwave and generate a report. This works on Window only.
+# ## View Layout in SIwave
+#
+# The SIwave user interface can be visualized and manipulated
+# using the SIwave user interface. This command works on Window OS only.
-# from pyaedt import Siwave
-# siwave = Siwave("2023.2")
+# +
+# siwave = pyaedt.Siwave("2023.2")
# siwave.open_project(siwave_file)
# report_file = os.path.join(temp_folder,'Ansys.htm')
-#
+
# siwave.export_siwave_report("myDCIR_4", report_file)
# siwave.close_project()
# siwave.quit_application()
+# -
+
+# Clean up the temporary files and directory.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/02_edb_to_ipc2581.py b/examples/00-EDB/02_edb_to_ipc2581.py
index f5733929697..230dd25815e 100644
--- a/examples/00-EDB/02_edb_to_ipc2581.py
+++ b/examples/00-EDB/02_edb_to_ipc2581.py
@@ -1,53 +1,36 @@
-"""
-EDB: IPC2581 export
--------------------
-This example shows how you can use PyAEDT to export an IPC2581 file.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: IPC2581 export
+#
+# This example shows how you can use PyAEDT to export an IPC2581 file.
+#
# Perform required imports, which includes importing a section.
import os
import pyaedt
+import tempfile
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
# Download the AEDB file and copy it in the temporary folder.
-
-temp_folder = pyaedt.generate_unique_folder_name()
-targetfile = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_folder)
-
-
-ipc2581_file = os.path.join(temp_folder, "Ansys_Hsd.xml")
-
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+targetfile = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',
+ destination=temp_dir.name)
+ipc2581_file_name = os.path.join(temp_dir.name, "Ansys_Hsd.xml")
print(targetfile)
-
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
-# Launch the :class:`pyaedt.Edb` class, using EDB 2023 R2 and SI units.
+# ## Launch EDB
+#
+# Launch the `pyaedt.Edb` class, using EDB 2023.
+# > Note that length dimensions passed to EDB are in SI units.
edb = pyaedt.Edb(edbpath=targetfile, edbversion="2023.2")
-
-###############################################################################
-# Parametrize net
-# ~~~~~~~~~~~~~~~
-# Parametrize a net.
+# Parametrize the width of a trace.
edb.modeler.parametrize_trace_width(
"A0_N", parameter_name=pyaedt.generate_unique_name("Par"), variable_value="0.4321mm"
)
-###############################################################################
-# Cutout
-# ~~~~~~
-# Create a cutout.
+# Create a cutout and plot it.
+
signal_list = []
for net in edb.nets.netlist:
if "PCIe" in net:
@@ -61,25 +44,17 @@
use_pyaedt_extent_computing=True,
extent_defeature=0,
)
-
-###############################################################################
-# Plot cutout
-# ~~~~~~~~~~~
-# Plot cutout before exporting to IPC2581 file.
-
edb.nets.plot(None, None, color_by_net=True)
-###############################################################################
-# Create IPC2581 file
-# ~~~~~~~~~~~~~~~~~~~
-# Create the IPC2581 file.
+# Export the EDB to an IPC2581 file.
-edb.export_to_ipc2581(ipc2581_file, "inch")
-print("IPC2581 File has been saved to {}".format(ipc2581_file))
+edb.export_to_ipc2581(ipc2581_file_name, "inch")
+print("IPC2581 File has been saved to {}".format(ipc2581_file_name))
-###############################################################################
# Close EDB
-# ~~~~~~~~~
-# Close EDB.
edb.close_edb()
+
+# Clean up the temporary directory
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/03_5G_antenna_example.py b/examples/00-EDB/03_5G_antenna_example.py
deleted file mode 100644
index 4d490fccef5..00000000000
--- a/examples/00-EDB/03_5G_antenna_example.py
+++ /dev/null
@@ -1,281 +0,0 @@
-"""
-EDB: 5G linear array antenna
-----------------------------
-This example shows how you can use HFSS 3D Layout to create and solve a 5G linear array antenna.
-"""
-
-##########################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
-
-import tempfile
-import pyaedt
-import os
-
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode. The default is ``False``.
-
-non_graphical = False
-
-
-class Patch:
- def __init__(self, width=0.0, height=0.0, position=0.0):
- self.width = width
- self.height = height
- self.position = position
-
- @property
- def points(self):
- return [
- [self.position, -self.height / 2],
- [self.position + self.width, -self.height / 2],
- [self.position + self.width, self.height / 2],
- [self.position, self.height / 2],
- ]
-
-
-class Line:
- def __init__(self, length=0.0, width=0.0, position=0.0):
- self.length = length
- self.width = width
- self.position = position
-
- @property
- def points(self):
- return [
- [self.position, -self.width / 2],
- [self.position + self.length, -self.width / 2],
- [self.position + self.length, self.width / 2],
- [self.position, self.width / 2],
- ]
-
-
-class LinearArray:
- def __init__(self, nb_patch=1, array_length=10e-3, array_width=5e-3):
- self.nbpatch = nb_patch
- self.length = array_length
- self.width = array_width
-
- @property
- def points(self):
- return [
- [-1e-3, -self.width / 2 - 1e-3],
- [self.length + 1e-3, -self.width / 2 - 1e-3],
- [self.length + 1e-3, self.width / 2 + 1e-3],
- [-1e-3, self.width / 2 + 1e-3],
- ]
-
-
-tmpfold = tempfile.gettempdir()
-aedb_path = os.path.join(tmpfold, pyaedt.generate_unique_name("pcb") + ".aedb")
-print(aedb_path)
-edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
-
-
-###############################################################################
-# Add stackup layers
-# ~~~~~~~~~~~~~~~~~~
-# Add the stackup layers.
-#
-if edb:
- edb.stackup.add_layer("Virt_GND")
- edb.stackup.add_layer("Gap", "Virt_GND", layer_type="dielectric", thickness="0.05mm", material="Air")
- edb.stackup.add_layer("GND", "Gap")
- edb.stackup.add_layer("Substrat", "GND", layer_type="dielectric", thickness="0.5mm", material="Duroid (tm)")
- edb.stackup.add_layer("TOP", "Substrat")
-
-###############################################################################
-# Create linear array
-# ~~~~~~~~~~~~~~~~~~~
-# Create the first patch of the linear array.
-
-first_patch = Patch(width=1.4e-3, height=1.2e-3, position=0.0)
-edb.modeler.create_polygon(first_patch.points, "TOP", net_name="Array_antenna")
-# First line
-first_line = Line(length=2.4e-3, width=0.3e-3, position=first_patch.width)
-edb.modeler.create_polygon(first_line.points, "TOP", net_name="Array_antenna")
-
-###############################################################################
-# Patch linear array
-# ~~~~~~~~~~~~~~~~~~
-# Patch the linear array.
-
-patch = Patch(width=2.29e-3, height=3.3e-3)
-line = Line(length=1.9e-3, width=0.2e-3)
-linear_array = LinearArray(nb_patch=8, array_width=patch.height)
-
-current_patch = 1
-current_position = first_line.position + first_line.length
-
-while current_patch <= linear_array.nbpatch:
- patch.position = current_position
- edb.modeler.create_polygon(patch.points, "TOP", net_name="Array_antenna")
- current_position += patch.width
- if current_patch < linear_array.nbpatch:
- line.position = current_position
- edb.modeler.create_polygon(line.points, "TOP", net_name="Array_antenna")
- current_position += line.length
- current_patch += 1
-
-linear_array.length = current_position
-
-
-###############################################################################
-# Add ground
-# ~~~~~~~~~~
-# Add a ground.
-
-edb.modeler.create_polygon(linear_array.points, "GND", net_name="GND")
-
-
-###############################################################################
-# Add connector pin
-# ~~~~~~~~~~~~~~~~~
-# Add a central connector pin.
-
-edb.padstacks.create(padstackname="Connector_pin", holediam="100um", paddiam="0", antipaddiam="200um")
-con_pin = edb.padstacks.place(
- [first_patch.width / 4, 0],
- "Connector_pin",
- net_name="Array_antenna",
- fromlayer="TOP",
- tolayer="GND",
- via_name="coax",
-)
-
-
-###############################################################################
-# Add connector ground
-# ~~~~~~~~~~~~~~~~~~~~
-# Add a connector ground.
-
-edb.modeler.create_polygon(first_patch.points, "Virt_GND", net_name="GND")
-edb.padstacks.create("gnd_via", "100um", "0", "0")
-con_ref1 = edb.padstacks.place(
- [first_patch.points[0][0] + 0.2e-3, first_patch.points[0][1] + 0.2e-3],
- "gnd_via",
- fromlayer="GND",
- tolayer="Virt_GND",
- net_name="GND",
-)
-con_ref2 = edb.padstacks.place(
- [first_patch.points[1][0] - 0.2e-3, first_patch.points[1][1] + 0.2e-3],
- "gnd_via",
- fromlayer="GND",
- tolayer="Virt_GND",
- net_name="GND",
-)
-con_ref3 = edb.padstacks.place(
- [first_patch.points[2][0] - 0.2e-3, first_patch.points[2][1] - 0.2e-3],
- "gnd_via",
- fromlayer="GND",
- tolayer="Virt_GND",
- net_name="GND",
-)
-con_ref4 = edb.padstacks.place(
- [first_patch.points[3][0] + 0.2e-3, first_patch.points[3][1] - 0.2e-3],
- "gnd_via",
- fromlayer="GND",
- tolayer="Virt_GND",
- net_name="GND",
-)
-
-
-###############################################################################
-# Add excitation port
-# ~~~~~~~~~~~~~~~~~~~
-# Add an excitation port.
-
-edb.padstacks.set_solderball(con_pin, "Virt_GND", isTopPlaced=False, ballDiam=0.1e-3)
-port_name = edb.padstacks.create_coax_port(con_pin)
-
-
-###############################################################################
-# Plot geometry
-# ~~~~~~~~~~~~~
-# Plot the geometry.
-
-edb.nets.plot(None)
-
-###############################################################################
-# Save and close Edb instance prior to opening it in Electronics Desktop.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Save EDB.
-
-edb.save_edb()
-edb.close_edb()
-print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path))
-###############################################################################
-# Launch HFSS 3D Layout and open EDB
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Launch HFSS 3D Layout and open EDB.
-
-h3d = pyaedt.Hfss3dLayout(projectname=aedb_path, specified_version="2023.2", new_desktop_session=True,
- non_graphical=non_graphical)
-
-###############################################################################
-# Plot geometry
-# ~~~~~~~~~~~~~~~~~
-# Plot the geometry. The EDB methods are also accessible from the ``Hfss3dlayout`` class.
-
-h3d.modeler.edb.nets.plot(None)
-
-###############################################################################
-# Create setup and sweeps
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Getters and setters facilitate the settings on the nested property dictionary.
-# Previously, you had to use these commands:
-#
-# - ``setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["AdaptiveFrequency"] = "20GHz"``
-# - ``setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["MaxPasses"] = 4``
-#
-# You can now use the simpler approach that follows.
-
-setup = h3d.create_setup()
-
-setup["AdaptiveFrequency"] = "20GHz"
-setup["AdaptiveSettings/SingleFrequencyDataList/AdaptiveFrequencyData/MaxPasses"] = 4
-h3d.create_linear_count_sweep(
- setupname=setup.name,
- unit="GHz",
- freqstart=20,
- freqstop=50,
- num_of_freq_points=1001,
- sweepname="sweep1",
- sweep_type="Interpolating",
- interpolation_tol_percent=1,
- interpolation_max_solutions=255,
- save_fields=False,
- use_q3d_for_dc=False,
-)
-
-
-###############################################################################
-# Solve setup and create report
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Solve the project and create a report.
-
-h3d.analyze()
-h3d.post.create_report(["db(S({0},{1}))".format(port_name, port_name)])
-
-
-###############################################################################
-# Plot results outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot results using Matplotlib.
-
-solution = h3d.post.get_solution_data(["S({0},{1})".format(port_name, port_name)])
-solution.plot()
-
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
-# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
-# All methods provide for saving the project before closing AEDT.
-
-h3d.save_project()
-h3d.release_desktop()
diff --git a/examples/00-EDB/03_5G_antenna_example_parametrics.py b/examples/00-EDB/03_5G_antenna_example_parametrics.py
index 771b745f6b8..692f7539c6d 100644
--- a/examples/00-EDB/03_5G_antenna_example_parametrics.py
+++ b/examples/00-EDB/03_5G_antenna_example_parametrics.py
@@ -1,12 +1,10 @@
-"""
-EDB: Layout Components
-----------------------
-This example shows how you can use EDB to create a layout component parametrics and use it in HFSS 3D.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: Layout Components
+#
+# This example shows how you can use EDB to create a parametric component using
+# 3D Layout and use it in HFSS 3D.
+
+# ## Perform required imports
+#
# Perform required imports, which includes importing the ``Hfss3dlayout`` object
# and initializing it on version 2023 R2.
@@ -14,22 +12,16 @@
import pyaedt
import os
-
-##########################################################
# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode. The default is ``False``.
-
-
non_graphical = False
-##########################################################
-# Creating data classes
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create data classes
+#
# Data classes are useful to do calculations and store variables.
-# We create 3 Data classes for Patch, Line and Array
+# There are three data classes: ``Patch``, ``Line``, and ``Array``.
+# +
class Patch:
def __init__(self, width=0.0, height=0.0, position=0.0):
self.width = width
@@ -76,24 +68,17 @@ def points(self):
["{}+1e-3".format(self.length), "{}/2+1e-3".format(self.width)],
[-1e-3, "{}/2+1e-3".format(self.width)],
]
+# -
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
+# ## Launch EDB
+#
# PyAEDT.Edb allows to open existing Edb project or create a new empty project.
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+aedb_path = os.path.join(temp_dir.name, "linear_array.aedb")
+edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2") # Create an instance of the Edb class.
-tmpfold = tempfile.gettempdir()
-aedb_path = os.path.join(tmpfold, pyaedt.generate_unique_name("pcb") + ".aedb")
-print(aedb_path)
-edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
-
-###############################################################################
# Add stackup layers
-# ~~~~~~~~~~~~~~~~~~
-# Add the stackup layers.
-
-
edb.stackup.add_layer("Virt_GND")
edb.stackup.add_layer("Gap", "Virt_GND", layer_type="dielectric", thickness="0.05mm", material="Air")
@@ -101,31 +86,29 @@ def points(self):
edb.stackup.add_layer("Substrat", "GND", layer_type="dielectric", thickness="0.5mm", material="Duroid (tm)")
edb.stackup.add_layer("TOP", "Substrat")
-###############################################################################
-# Create linear array
-# ~~~~~~~~~~~~~~~~~~~
-# Create the first patch of the linear array.
-
-
+# Create the the first patch and feed line using the ``Patch``, ``Line``classes defined above.
+#
+# Define parameters:
+# +
edb["w1"] = 1.4e-3
edb["h1"] = 1.2e-3
edb["initial_position"] = 0.0
edb["l1"] = 2.4e-3
edb["trace_w"] = 0.3e-3
+
first_patch = Patch(width="w1", height="h1", position="initial_position")
edb.modeler.create_polygon(first_patch.points, "TOP", net_name="Array_antenna")
+# -
+
# First line
first_line = Line(length="l1", width="trace_w", position=first_patch.width)
edb.modeler.create_polygon(first_line.points, "TOP", net_name="Array_antenna")
-###############################################################################
-# Patch linear array
-# ~~~~~~~~~~~~~~~~~~
-# Patch the linear array.
-
+# Now use the ``LinearArray`` class to create the array.
+# +
edb["w2"] = 2.29e-3
edb["h2"] = 3.3e-3
edb["l2"] = 1.9e-3
@@ -149,20 +132,13 @@ def points(self):
current_patch += 1
linear_array.length = current_position
+# -
-###############################################################################
-# Add ground
-# ~~~~~~~~~~
-# Add a ground.
-
+# Add the ground conductor.
edb.modeler.create_polygon(linear_array.points, "GND", net_name="GND")
-###############################################################################
-# Add connector pin
-# ~~~~~~~~~~~~~~~~~
-# Add a central connector pin.
-
+# Add the connector pin to use to assign the port.
edb.padstacks.create(padstackname="Connector_pin", holediam="100um", paddiam="0", antipaddiam="200um")
con_pin = edb.padstacks.place(
@@ -174,12 +150,8 @@ def points(self):
via_name="coax",
)
-###############################################################################
-# Add connector ground
-# ~~~~~~~~~~~~~~~~~~~~
# Add a connector ground.
-
edb.modeler.create_polygon(first_patch.points, "Virt_GND", net_name="GND")
edb.padstacks.create("gnd_via", "100um", "0", "0")
edb["via_spacing"] = 0.2e-3
@@ -212,168 +184,139 @@ def points(self):
net_name="GND",
)
-
-################################################################################
-# Add excitation port
-# ~~~~~~~~~~~~~~~~~~~
-# Add an excitation port.
-
+# Define the port.
edb.padstacks.set_solderball(con_pin, "Virt_GND", isTopPlaced=False, ballDiam=0.1e-3)
port_name = edb.padstacks.create_coax_port(con_pin)
-
-###############################################################################
-# Plot geometry
-# ~~~~~~~~~~~~~
-# Plot the geometry.
-
+# Display the model using the ``Edb.nets.plot()`` method.
edb.nets.plot()
-
-###############################################################################
-# Save and close Edb instance prior to opening it in Electronics Desktop.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Save EDB.
-
+# The EDB is complete. Now close the EDB and import it into HFSS as a "Layout Component".
edb.save_edb()
edb.close_edb()
print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path))
+# ## 3D component in HFSS
+#
+# First create an instance of the ``pyaedt.Hfss`` class. If you set
+# > ``non_graphical = False
+#
+# then AEDT user interface will be visible after the following cell is executed. It is now possible
+# to monitor the progress in the UI as each of the following cells is executed. All commands can be run
+# without the UI by chaning the value of ``non_graphical``.
-###############################################################################
-# Launch HFSS 3D
-# ~~~~~~~~~~~~~~
-# Launch HFSS 3D.
+h3d = pyaedt.Hfss(projectname="Demo_3DComp",
+ designname="Linear_Array",
+ specified_version="2023.2",
+ new_desktop_session=True,
+ non_graphical=non_graphical,
+ close_on_exit=True,
+ solution_type="Terminal")
-h3d = pyaedt.Hfss(specified_version="2023.2", new_desktop_session=True, close_on_exit=True, solution_type="Terminal")
+# Set units to ``mm``.
-###############################################################################
-# Add the layout component
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Hfss allows user to add Layout components (aedb) or 3D Components into a 3D Design
-# and benefit of different functionalities like parametrization, mesh fusion and others.
+h3d.modeler.model_units = "mm"
+# ## Import the EDB as a 3D component
+#
+# One or more layout components can be imported into HFSS. The combination of layout data and 3D CAD data helps streamline
+# model creation and setup.
component = h3d.modeler.insert_layout_component(aedb_path, parameter_mapping=True)
-###############################################################################
-# Edit Parameters
-# ~~~~~~~~~~~~~~~
-# If a layout component is parametric, parameters can be exposed and changed in HFSS
-
+# ## Expose the component parameters
+#
+# If a layout component is parametric, you can expose and change parameters in HFSS
+# +
component.parameters
w1_name = "{}_{}".format("w1", h3d.modeler.user_defined_component_names[0])
h3d[w1_name]= 0.0015
-
-###############################################################################
-# Boundaries
-# ~~~~~~~~~~
-# To run the simulation we need an airbox to which apply radiation boundaries.
-# We don't need to create ports because are embedded in layout component.
-
-
+# -
+
+# ### Radiation Boundary Assignment
+#
+# The 3D domain includes the air volume surrounding the antenna. This antenna will be simulted from 20 GHz - 50 GHz.
+#
+# A "radiation boundary" will be assigned to the outer boundaries of the domain.
+# This boundary should be roughly one quarter wavelength away from the radiating strucure:
+#
+# $$ \lambda/4 = \frac{c_0}{4 f} \approx 2.8mm $$
+
+# +
h3d.modeler.fit_all()
-
-h3d.modeler.create_air_region(130,400,1000, 130,400,300)
+h3d.modeler.create_air_region(2.8, 2.8, 2.8, 2.8, 2.8, 2.8, is_percentage=False)
h3d.assign_radiation_boundary_to_objects("Region")
+# -
-###############################################################################
-# Create setup and sweeps
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Getters and setters facilitate the settings on the nested property dictionary.
-#
-# - ``setup.props['Frequency']="20GHz"``
-#
-#
-# You can now use the simpler approach that follows.
-#
-#
-
+# ### Set up analysis
+#
+# The finite element mesh is adapted iteratively. The maximum number of adaptive passes is set using the ``MaximumPasses`` property. This model converges such that the $S_{11}$ is independent of the mesh. The default accuracy setting is:
+# $$ \max(|\Delta S|) < 0.02 $$
setup = h3d.create_setup()
-
setup.props['Frequency']="20GHz"
-setup.props['MaximumPasses'] = 2
+setup.props['MaximumPasses'] = 10
+
+# Specify properties of the frequency sweep:
-sweep1 = setup.add_sweep()
+sweep1 = setup.add_sweep(sweepname="20GHz_to_50GHz")
sweep1.props["RangeStart"]="20GHz"
sweep1.props["RangeEnd"]="50GHz"
sweep1.update()
-###############################################################################
-# Solve setup and create report
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Solve the project and create a report.
-
-
+# Solve the project
h3d.analyze()
-
-
-
-###############################################################################
-# Plot results outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot results outside AEDT
+#
# Plot results using Matplotlib.
trace = h3d.get_traces_for_plot()
solution = h3d.post.get_solution_data(trace[0])
solution.plot()
+# ## Plot far fields in AEDT
+#
+# Plot radiation patterns in AEDT.
-################################################################################
-# Plot Far Fields in AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Plot Radiation patterns in AEDT.
-
-
+# +
variations = {}
variations["Freq"] = ["20GHz"]
variations["Theta"] = ["All"]
variations["Phi"] = ["All"]
h3d.insert_infinite_sphere( name="3D")
-
new_report = h3d.post.reports_by_category.far_field("db(RealizedGainTotal)", h3d.nominal_adaptive, "3D")
new_report.variations = variations
new_report.primary_sweep = "Theta"
new_report.create("Realized2D")
+# -
-
-################################################################################
-# Plot Far Fields in AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Plot Radiation patterns in AEDT.
-
-
+# ## Plot far fields in AEDT
+#
+# Plot radiation patterns in AEDT
new_report.report_type = "3D Polar Plot"
new_report.secondary_sweep = "Phi"
new_report.create("Realized3D")
-
-################################################################################
-# Plot Far Fields outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot Radiation patterns outside AEDT.
-
-
+# ## Plot far fields outside AEDT
+#
+# Plot radiation patterns outside AEDT
solutions_custom = new_report.get_solution_data()
solutions_custom.plot_3d()
-################################################################################
-# Plot E Field on nets and layers
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot E Field on nets and layers in AEDT.
-
+# ## Plot E Field on nets and layers
+#
+# Plot E Field on nets and layers in AEDT
h3d.post.create_fieldplot_layers_nets(
[["TOP","Array_antenna"]],
@@ -382,17 +325,17 @@ def points(self):
plot_name="E_Layers",
)
-
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
-# After the simulation completes, you can close AEDT or release it using the
+# ## Close AEDT
+#
+# After the simulation completes, the application can be released from the
# :func:`pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing AEDT.
-
-h3d.save_project(os.path.join(tmpfold, "test_layout.aedt"))
+h3d.save_project(os.path.join(temp_dir, "test_layout.aedt"))
h3d.release_desktop()
+# ### Clean up the temporary directory
+#
+# The following command removes the project and the temporary directory. If you'd like to save this project, save it to a folder of your choice prior to running the following cell.
-
+temp_dir.cleanup()
diff --git a/examples/00-EDB/04_edb_parametrized_design.py b/examples/00-EDB/04_edb_parametrized_design.py
index abc2ed53286..29394147992 100644
--- a/examples/00-EDB/04_edb_parametrized_design.py
+++ b/examples/00-EDB/04_edb_parametrized_design.py
@@ -1,39 +1,34 @@
-"""
-EDB: fully parametrized design
-------------------------------
-This example shows how you can use HFSS 3D Layout to create and solve a parametric design.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports, which includes importing the ``Hfss3dlayout`` object
-# and initializing it on version 2023 R2.
+# # EDB: fully parametrized design
+#
+# This example shows how to use the EDB interface along with HFSS 3D Layout to create and solve a
+# parameterized layout. The layout shows a differential via transition on a printed circuit board with
+# back-to-back microstrip to stripline transitions. The model is fully parameterized to enable investigation of
+# the transition performance on the many degrees of freedom.
+#
+# The resulting model is shown below
+#
+#
import pyaedt
import os
+import tempfile
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode. The default is ``False``.
+# ## Set non-graphical mode
+#
+# Set non-graphical mode. The default is ``False``, which opens
+# the AEDT UI.
non_graphical = False
-##########################################################
-# Launch EDB
-# ~~~~~~~~~~
# Launch EDB.
-aedb_path = os.path.join(pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("pcb") + ".aedb")
-print(aedb_path)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+aedb_path = os.path.join(temp_dir.name, "pcb.aedb")
edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
-######################################################################
-# Define parameters
-# ~~~~~~~~~~~~~~~~~
# Define the parameters.
+# +
params = {"$ms_width": "0.4mm",
"$sl_width": "0.2mm",
"$ms_spacing": "0.2mm",
@@ -42,7 +37,7 @@
"$via_diam": "0.3mm",
"$pad_diam": "0.6mm",
"$anti_pad_diam": "0.7mm",
- "$pcb_len": "30mm",
+ "$pcb_len": "15mm",
"$pcb_w": "5mm",
"$x_size": "1.2mm",
"$y_size": "1mm",
@@ -50,13 +45,10 @@
for par_name in params:
edb.add_project_variable(par_name, params[par_name])
+# -
-######################################################################
-# Define stackup layers
-# ~~~~~~~~~~~~~~~~~~~~~
# Define the stackup layers from bottom to top.
-
layers = [{"name": "bottom", "layer_type": "signal", "thickness": "35um", "material": "copper"},
{"name": "diel_3", "layer_type": "dielectric", "thickness": "275um", "material": "FR4_epoxy"},
{"name": "sig_2", "layer_type": "signal", "thickness": "35um", "material": "copper"},
@@ -65,18 +57,17 @@
{"name": "diel_1", "layer_type": "dielectric", "thickness": "275um", "material": "FR4_epoxy"},
{"name": "top", "layer_type": "signal", "thickness": "35um", "material": "copper"}]
+# Create the EDB stackup.
+# Define the bottom layer
-# Create EDB stackup.
-# Bottom layer
prev = None
for layer in layers:
- edb.stackup.add_layer(layer["name"], base_layer=prev, layer_type=layer["layer_type"], thickness=layer["thickness"],
- material=layer["material"])
+ edb.stackup.add_layer(layer["name"], base_layer=prev,
+ layer_type=layer["layer_type"],
+ thickness=layer["thickness"],
+ material=layer["material"])
prev = layer["name"]
-###############################################################################
-# Create padstack for signal via
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a parametrized padstack for the signal via.
signal_via_padstack = "automated_via"
@@ -93,18 +84,12 @@
stop_layer=layers[-3]["name"]
)
-###############################################################################
-# Assign net names
-# ~~~~~~~~~~~~~~~~
-# # Assign net names. There are only two signal nets.
+# Assign net names. There are only two signal nets.
net_p = "p"
net_n = "n"
-###############################################################################
-# Place signal vias
-# ~~~~~~~~~~~~~~~~~
-# Place signal vias.
+# Place the signal vias.
edb.padstacks.place(
position=["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing)/2"],
@@ -139,11 +124,9 @@
)
-# ###############################################################################
-# Draw parametrized traces
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Draw parametrized traces.
-# Trace the width and the routing (Microstrip-Stripline-Microstrip).
+# ## Draw parametrized traces
+#
+# Trace width and the routing (Microstrip-Stripline-Microstrip).
# Applies to both p and n nets.
width = ["$ms_width", "$sl_width", "$ms_width"] # Trace width, n and p
@@ -192,10 +175,8 @@
["$pcb_len", "-($ms_width + $ms_spacing)/2"],
],
]
-# ###############################################################################
-# Add traces to EDB
-# ~~~~~~~~~~~~~~~~~
-# Add traces to EDB.
+
+# Add traces to the EDB.
trace_p = []
trace_n = []
@@ -203,10 +184,7 @@
trace_p.append(edb.modeler.create_trace(points_p[n], route_layer[n], width[n], net_p, "Flat", "Flat"))
trace_n.append(edb.modeler.create_trace(points_n[n], route_layer[n], width[n], net_n, "Flat", "Flat"))
-###############################################################################
-# Create wave ports
-# ~~~~~~~~~~~~~~~~~
-# Create wave ports:
+# Create the wave ports
edb.hfss.create_differential_wave_port(trace_p[0].id, ["0.0", "($ms_width+$ms_spacing)/2"],
trace_n[0].id, ["0.0", "-($ms_width+$ms_spacing)/2"],
@@ -215,10 +193,7 @@
trace_n[2].id, ["$pcb_len", "-($ms_width + $ms_spacing)/2"],
"wave_port_2")
-###############################################################################
-# Draw ground polygons
-# ~~~~~~~~~~~~~~~~~~~~
-# Draw ground polygons.
+# Draw a conducting rectangle on the the ground layers.
gnd_poly = [[0.0, "-$pcb_w/2"],
["$pcb_len", "-$pcb_w/2"],
@@ -228,6 +203,7 @@
# Void in ground for traces on the signal routing layer
+# +
void_poly = [["$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2"],
["$pcb_len/3 + $via_spacing", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2"],
["$pcb_len/3 + 2*$via_spacing",
@@ -246,9 +222,11 @@
["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"]]
void_shape = edb.modeler.Shape("polygon", points=void_poly)
+# -
-# Add ground layers
+# Add ground conductors.
+# +
for layer in layers[:-1:2]:
# add void if the layer is the signal routing layer.
@@ -258,37 +236,27 @@
layer_name=layer["name"],
voids=void,
net_name="gnd")
+# -
-
-###############################################################################
-# Plot EDB
-# ~~~~~~~~
-# Plot EDB.
+# Plot the layout.
edb.nets.plot(None)
-###############################################################################
-# Save EDB
-# ~~~~~~~~
-# Save EDB.
+# Save the EDB.
edb.save_edb()
edb.close_edb()
-
-###############################################################################
-# Open EDB in AEDT
-# ~~~~~~~~~~~~~~~~
-# Open EDB in AEDT.
+# Open the project in HFSS 3D Layout.
h3d = pyaedt.Hfss3dLayout(projectname=aedb_path, specified_version="2023.2",
non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Add HFSS simulation setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# # Add HFSS simulation setup
+#
# Add HFSS simulation setup.
+# +
setup = h3d.create_setup()
setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["MaxPasses"] = 3
@@ -305,38 +273,29 @@
save_fields=False,
use_q3d_for_dc=False,
)
+# -
+
+# Define the differential pairs to used to calculate differential and common mode
+# s-parameters.
-###############################################################################
-# Set Differential Pairs.
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Define the differential pairs to be used in the postprocessing.
h3d.set_differential_pair(diff_name="In", positive_terminal="wave_port_1:T1", negative_terminal="wave_port_1:T2")
h3d.set_differential_pair(diff_name="Out", positive_terminal="wave_port_2:T1", negative_terminal="wave_port_2:T2")
-###############################################################################
-# Start HFSS solver
-# ~~~~~~~~~~~~~~~~~
-# Start the HFSS solver by uncommenting the ``h3d.analyze()`` command.
+# Solve the project.
h3d.analyze()
-
-###############################################################################
-# Generate Plot
-# ~~~~~~~~~~~~~
-# Generate the plot of differential pairs.
+# Plot the results and shut down AEDT.
solutions = h3d.post.get_solution_data(["dB(S(In,In))", "dB(S(In,Out))"], context="Differential Pairs")
solutions.plot()
-
-
-
-
-
h3d.release_desktop()
-###############################################################################
# Note that the ground nets are only connected to each other due
# to the wave ports. The problem with poor grounding can be seen in the
-# S-parameters. Try to modify this script to add ground vias and eliminate
-# the resonance.
+# S-parameters. This example can be downloaded as a Jupyter Notebook, so
+# you can modify it. Try changing parameters or adding ground vias to improve performance.
+#
+# The final cell cleans up the temporary directory, removing all files.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/05_Plot_nets.py b/examples/00-EDB/05_Plot_nets.py
index 19a909f51cb..45519aa3af4 100644
--- a/examples/00-EDB/05_Plot_nets.py
+++ b/examples/00-EDB/05_Plot_nets.py
@@ -1,65 +1,59 @@
-"""
-EDB: plot nets with Matplotlib
-------------------------------
-This example shows how you can use the ``Edb`` class to plot a net or a layout.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: plot nets with Matplotlib
+#
+# This example shows how to use the ``Edb`` class to view nets, layers and
+# via geometry directly in Python. The methods demonstrated in this example
+# rely on
+# [matplotlib](https://matplotlib.org/cheatsheets/_images/cheatsheets-1.png).
+
+# ## Perform required imports
+
# Perform required imports, which includes importing a section.
import os
import pyaedt
+import tempfile
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
-# Download the AEDT file and copy it into the temporary folder.
-
-temp_folder = pyaedt.generate_unique_folder_name()
+# Download the EDB and copy it into the temporary folder.
-targetfolder = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_folder)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+targetfolder = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',
+ destination=temp_dir.name)
-
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
-# Launch the :class:`pyaedt.Edb` class, using EDB 2023 R2 and SI units.
+# Create an instance of the Electronics Database usig the
+# `pyaedt.Edb` class.
+#
+# > Note that units are SI.
edb = pyaedt.Edb(edbpath=targetfolder, edbversion="2023.2")
-###############################################################################
-# Plot custom set of nets colored by layer
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot a custom set of nets colored by layer (default).
+# Display the nets on a layer. You can display the net geometry directly in Python using ``matplotlib`` from
+# the ``pyaedt.Edb`` class.
edb.nets.plot("AVCC_1V3")
-###############################################################################
-# Plot custom set of nets colored by nets
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot a custom set of nets colored by nets.
+# You can view multiple nets by passing a list containing the net
+# names to the ``plot()`` method.
edb.nets.plot(["GND", "GND_DP", "AVCC_1V3"], color_by_net=True)
-###############################################################################
-# Plot all nets on a layer colored by nets
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot all nets on a layer colored by nets
+# You can display all copper on a single layer by passing ``None``
+# as the first argument. The second argument is a list
+# of layers to plot. In this case, only one
+# layer is to be displayed.
-edb.nets.plot(None, ["1_Top"], color_by_net=True, plot_components_on_top=True)
+edb.nets.plot(None, ["1_Top"], color_by_net=True,
+ plot_components_on_top=True)
-###############################################################################
-# Plot stackup and some padstack definition
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Plot all nets on a layer colored by nets
+# Display a side view of the layers and padstack geometry using the
+# ``Edb.stackup.plot()`` method.
-edb.stackup.plot(scale_elevation=False,plot_definitions=["c100hn140", "c35"])
+edb.stackup.plot(scale_elevation=False,
+ plot_definitions=["c100hn140", "c35"])
-###############################################################################
-# Close EDB
-# ~~~~~~~~~
-# Close EDB.
+# Close the EDB.
edb.close_edb()
+
+# Remove all files and the temporary directory.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/06_Advanced_EDB.py b/examples/00-EDB/06_Advanced_EDB.py
index b0cfab95b74..d6d22a58918 100644
--- a/examples/00-EDB/06_Advanced_EDB.py
+++ b/examples/00-EDB/06_Advanced_EDB.py
@@ -1,49 +1,39 @@
-"""
-EDB: parametric via creation
-----------------------------
-This example shows how you can use EDB to create a layout.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+# # EDB: parametric via creation
+#
+# This example shows how you can use EDB to create a layout.
+#
+# First import the required Python packages.
+
import os
import numpy as np
import pyaedt
+import tempfile
+# Create the EDB project.
-aedb_path = os.path.join(pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("via_opt") + ".aedb")
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+aedb_path = os.path.join(temp_dir.name, "parametric_via.aedb")
-###############################################################################
-# Create stackup
-# ~~~~~~~~~~~~~~
+# ## Create stackup
+#
# The ``StackupSimple`` class creates a stackup based on few inputs. This stackup
# is used later.
+#
+# Define a function to create the ground conductor.
-
-###############################################################################
-# Create ground plane
-# ~~~~~~~~~~~~~~~~~~~
-# Create a ground plane on specific layers.
-
-def _create_ground_planes(edb, layers):
+def create_ground_planes(edb, layers):
plane = edb.modeler.Shape("rectangle", pointA=["-3mm", "-3mm"], pointB=["3mm", "3mm"])
for i in layers:
edb.modeler.create_polygon(plane, i, net_name="GND")
-
-##################################################################################
-# Create EDB
-# ~~~~~~~~~~
-# Create EDB. If the path doesn't exist, PyAEDT automatically generates a new AEDB folder.
+# ## Create the EDB
+#
+# Create the EDB instance. If the path doesn't exist, PyAEDT automatically generates a new AEDB folder.
edb = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
-##################################################################################
-# Create stackup layers
-# ~~~~~~~~~~~~~~~~~~~~~
-# Create stackup layers.
+# Insert the stackup layers.
layout_count = 12
diel_material_name = "FR4_epoxy"
@@ -60,13 +50,13 @@ def _create_ground_planes(edb, layers):
soldermask_thickness=soldermask_thickness, dielectric_thickness=diel_thickness,
dielectric_material=diel_material_name)
+# ## Define parameters
+#
+# Define parameters to allow changes in the model dimesons. Parameters preceeded by
+# the ``$`` character have project-wide scope.
+# Without the ``$`` prefix, the parameter scope is limited to the design.
-##################################################################################
-# Create variables
-# ~~~~~~~~~~~~~~~~
-# Create all variables. If a variable has a ``$`` prefix, it is a project variable.
-# Otherwise, is a design variable.
-
+# +
giva_angle_rad = gvia_angle / 180 * np.pi
edb["$via_hole_size"] = "0.3mm"
@@ -75,12 +65,11 @@ def _create_ground_planes(edb, layers):
edb.add_design_variable("via_pitch", "1mm", is_parameter=True)
edb.add_design_variable("trace_in_width", "0.2mm", is_parameter=True)
edb.add_design_variable("trace_out_width", "0.1mm", is_parameter=True)
+# -
-##################################################################################
-# Create definitions
-# ~~~~~~~~~~~~~~~~~~
-# Create two definitions, one for the ground and one for the signal. The definitions
-# are parametric.
+# ## Define padstacks
+#
+# Create two padstck definitions, one for the ground via and one for the signal via.
edb.padstacks.create(padstackname="SVIA",
holediam="$via_hole_size",
@@ -91,19 +80,13 @@ def _create_ground_planes(edb, layers):
)
edb.padstacks.create(padstackname="GVIA", holediam="0.3mm", antipaddiam="0.7mm", paddiam="0.5mm")
-##################################################################################
-# Place padstack for signal
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
-# Place the padstack for the signal.
+# Place the signal via.
edb.padstacks.place([0, 0], "SVIA", net_name="RF")
-##################################################################################
-# Place padstack for ground
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
-# Place the padstack for the ground. A loop iterates and places multiple ground
-# vias on different positions.
+# Place the ground vias.
+# +
gvia_num_side = gvia_num / 2
if gvia_num_side % 2:
@@ -130,12 +113,11 @@ def _create_ground_planes(edb, layers):
edb.padstacks.place([xloc + "*-1", yloc], "GVIA", net_name="GND")
edb.padstacks.place([xloc + "*-1", yloc + "*-1"], "GVIA", net_name="GND")
+# -
-##################################################################################
-# Generate traces
-# ~~~~~~~~~~~~~~~
-# Generate and place parametric traces.
+# Draw the traces
+# +
edb.modeler.create_trace(
[[0, 0], [0, "-3mm"]], layer_name=trace_in_layer, net_name="RF", width="trace_in_width", start_cap_style="Flat", end_cap_style="Flat"
)
@@ -148,32 +130,25 @@ def _create_ground_planes(edb, layers):
start_cap_style="Flat",
end_cap_style="Flat",
)
+# -
-##################################################################################
-# Generate ground layers
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Generate and place ground layers.
+# Draw ground conductors
ground_layers = [i for i in edb.stackup.signal_layers.keys()]
ground_layers.remove(trace_in_layer)
ground_layers.remove(trace_out_layer)
-_create_ground_planes(edb=edb, layers=ground_layers)
+create_ground_planes(edb=edb, layers=ground_layers)
-##################################################################################
-# Plot Layout
-# ~~~~~~~~~~~
-# Generate and plot the layout.
+# Display the layout
-#edb.nets.plot(layers=["TOP", "L10"])
edb.stackup.plot(plot_definitions=["GVIA", "SVIA"])
-
-##################################################################################
-# Save EDB and close
-# ~~~~~~~~~~~~~~~~~~
-# Save EDB and close.
+# Save EDB and close the EDB.
edb.save_edb()
edb.close_edb()
-
print("aedb Saved in {}".format(aedb_path))
+
+# Clean up the temporary directory.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/08_CPWG.py b/examples/00-EDB/08_CPWG.py
index a6401426767..46f40d6067c 100644
--- a/examples/00-EDB/08_CPWG.py
+++ b/examples/00-EDB/08_CPWG.py
@@ -1,13 +1,11 @@
-"""
-EDB: fully parametrized CPWG design
------------------------------------
-This example shows how you can use HFSS 3D Layout to create a parametric design
-for a CPWG (coplanar waveguide with ground).
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: fully parametrized CPWG design
+
+# This example shows how you can use HFSS 3D Layout to create a parametric design
+# for a CPWG (coplanar waveguide with ground).
+
+
+# ## Perform required imports
+
# Perform required imports. Importing the ``Hfss3dlayout`` object initializes it
# on version 2023 R2.
@@ -15,26 +13,20 @@
import os
import numpy as np
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Set non-graphical mode
+
# Set non-graphical mode. The default is ``False``.
non_graphical = False
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
-# Launch EDB.
+# ## Launch EDB
aedb_path = os.path.join(pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("pcb") + ".aedb")
print(aedb_path)
edbapp = pyaedt.Edb(edbpath=aedb_path, edbversion="2023.2")
-###############################################################################
-# Define parameters
-# ~~~~~~~~~~~~~~~~~
-# Define parameters.
+# ## Define parameters
params = {"$ms_width": "0.4mm",
"$ms_clearance": "0.3mm",
@@ -43,19 +35,15 @@
for par_name in params:
edbapp.add_project_variable(par_name, params[par_name])
-###############################################################################
-# Create stackup
-# ~~~~~~~~~~~~~~
-# Create a symmetric stackup.
+
+# ## Create s symmetric stackup
edbapp.stackup.create_symmetric_stackup(2)
edbapp.stackup.plot()
-###############################################################################
-# Draw planes
-# ~~~~~~~~~~~
-# Draw planes.
+# ## Draw planes
+# +
plane_lw_pt = ["0mm", "-3mm"]
plane_up_pt = ["$ms_length", "3mm"]
@@ -67,11 +55,9 @@
upper_right_point=plane_up_pt)
layer_dict = {"TOP": top_layer_obj,
"BOTTOM": bot_layer_obj}
+# -
-###############################################################################
-# Draw trace
-# ~~~~~~~~~~
-# Draw a trace.
+# ## Draw a trace
trace_path = [["0", "0"], ["$ms_length", "0"]]
edbapp.modeler.create_trace(trace_path,
@@ -82,10 +68,7 @@
end_cap_style="Flat"
)
-###############################################################################
-# Create trace to plane clearance
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a trace to the plane clearance.
+# ## Create a trace to plane clearance
poly_void = edbapp.modeler.create_trace(trace_path, layer_name="TOP", net_name="gnd",
width="{}+2*{}".format("$ms_width", "$ms_clearance"),
@@ -93,11 +76,9 @@
end_cap_style="Flat")
edbapp.modeler.add_void(layer_dict["TOP"], poly_void)
-###############################################################################
-# Create ground via padstack and place ground stitching vias
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a ground via padstack and place ground stitching vias.
+# ## Create a ground via padstack and place ground stitching vias
+# +
edbapp.padstacks.create(padstackname="GVIA",
holediam="0.3mm",
paddiam="0.5mm",
@@ -109,43 +90,29 @@
for i in np.arange(1, 20):
edbapp.padstacks.place([str(i) + "mm", yloc_u], "GVIA", net_name="GND")
edbapp.padstacks.place([str(i) + "mm", yloc_l], "GVIA", net_name="GND")
+# -
-###############################################################################
-# Save and close EDB
-# ~~~~~~~~~~~~~~~~~~
-# Save and close EDB.
+# ## Save and close EDB
edbapp.save_edb()
edbapp.close_edb()
-###############################################################################
-# Open EDB in AEDT
-# ~~~~~~~~~~~~~~~~
-# Open EDB in AEDT.
+# ## Open EDB in AEDT
h3d = pyaedt.Hfss3dLayout(projectname=aedb_path, specified_version="2023.2",
non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Create wave ports
-# ~~~~~~~~~~~~~~~~~
-# Create wave ports.
+# ## Create wave ports
h3d.create_edge_port("line_3", 0, iswave=True, wave_vertical_extension=10, wave_horizontal_extension=10)
h3d.create_edge_port("line_3", 2, iswave=True, wave_vertical_extension=10, wave_horizontal_extension=10)
-###############################################################################
-# Edit airbox extents
-# ~~~~~~~~~~~~~~~~~~~
-# Edit airbox extents.
+# ## Edit airbox extents
h3d.edit_hfss_extents(air_vertical_positive_padding="10mm",
air_vertical_negative_padding="1mm")
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
-# Create an HFSS simulation setup.
+# ## Create setup
setup = h3d.create_setup()
setup["MaxPasses"]=2
@@ -165,25 +132,27 @@
use_q3d_for_dc=False,
)
-###############################################################################
-# Plot layout
-# ~~~~~~~~~~~
-# Plot layout
+# ## Plot layout
+# +
h3d.modeler.edb.nets.plot(None, None, color_by_net=True)
cp_name = h3d.modeler.clip_plane()
h3d.save_project()
+# -
+
+# ## Start HFSS solver
-###############################################################################
-# Start HFSS solver
-# ~~~~~~~~~~~~~~~~~
# Start the HFSS solver by uncommenting the ``h3d.analyze()`` command.
-h3d.analyze()
+# +
+# h3d.analyze()
+# -
+
+# ## Save AEDT
-# Save AEDT
+# +
aedt_path = aedb_path.replace(".aedb", ".aedt")
h3d.logger.info("Your AEDT project is saved to {}".format(aedt_path))
solutions = h3d.get_touchstone_data()[0]
@@ -191,7 +160,8 @@
solutions.plot()
h3d.post.create_fieldplot_cutplane(cp_name, "Mag_E", h3d.nominal_adaptive, intrinsincDict={"Freq":"3GHz", "Phase":"0deg"})
+# -
-# Release AEDT.
-h3d.release_desktop()
+# ## Release AEDT
+h3d.release_desktop()
diff --git a/examples/00-EDB/09_Configuration.py b/examples/00-EDB/09_Configuration.py
index 9d095755ff6..9a07d3ca74e 100644
--- a/examples/00-EDB/09_Configuration.py
+++ b/examples/00-EDB/09_Configuration.py
@@ -1,50 +1,42 @@
-"""
-EDB: Pin to Pin project
------------------------
-This example shows how you can create a project using a BOM file and configuration files.
-run anlasyis and get results.
-
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports. Importing the ``Hfss3dlayout`` object initializes it
+# # EDB: Pin to Pin project
+#
+# This example demonstrates the use of the Electronics
+# Database (EDB) interface to create a layout using the BOM and
+# a configuration file.
+
+# ## Perform required imports
+#
+# The ``Hfss3dlayout`` class provides an interface to
+# the 3D Layout editor in AEDT.
# on version 2023 R2.
import os
import pyaedt
+import tempfile
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode. The default is ``True``.
-
-non_graphical = True
-
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
-# Download the AEDB file and copy it in the temporary folder.
+# Download the AEDB file and copy it to a temporary folder.
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+target_aedb = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',
+ destination=temp_dir.name)
+print("Project folder is", target_aedb)
-project_path = pyaedt.generate_unique_folder_name()
-target_aedb = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=project_path)
-print("Project folder will be", target_aedb)
-
-###############################################################################
-# Launch EDB
-# ~~~~~~~~~~
-# Launch the :class:`pyaedt.Edb` class, using EDB 2023 R2 and SI units.
+# ## Launch EDB
+#
+# Launch the ``pyaedt.Edb`` class using EDB 2023 R2. Length units are SI.
edbapp = pyaedt.Edb(target_aedb, edbversion="2023.2")
-###############################################################################
-# Import Definitions
-# ~~~~~~~~~~~~~~~~~~
-# A definitions file is a json containing, for each part name the model associated.
-# Model can be RLC, Sparameter or Spice.
-# Once imported the definition is applied to the board.
-# In this example the json file is stored for convenience in aedb folder and has the following format:
+
+# ## Import definitions
+#
+# The definition file uses the [json](https://www.json.org/json-en.html) to
+# map layout part numbers to their corresponding models.
+#
+# The model may be an RLC, S-parameter, or
+# [SPICE](https://en.wikipedia.org/wiki/SPICE) model definition.
+# Once imported, the definition is applied to the components in the layout.
+# In this example, the JSON file is in the ``*.aedb`` folder and has the following format:
+# ``` json
# {
# "SParameterModel": {
# "GRM32_DC0V_25degC_series": "./GRM32_DC0V_25degC_series.s2p"
@@ -73,23 +65,32 @@
# }
# }
# }
+# ```
+#
+# The ``Edb.components.import_definitions()`` method imports the component definitions that map electrical models to the components in the simulation model.
-edbapp.components.import_definition(os.path.join(target_aedb, "1_comp_definition.json"))
+edbapp.components.import_definition(os.path.join(target_aedb,
+ "1_comp_definition.json"))
-###############################################################################
-# Import BOM
-# ~~~~~~~~~~
-# This step imports a BOM file in CSV format. The BOM contains the
-# reference designator, part name, component type, and default value.
-# Components not in the BOM are deactivated.
-# In this example the csv file is stored for convenience in aedb folder.
+# ## Import BOM
+#
+# The bill of materials (BOM) file provides the list of all components
+# by reference designator, part name, component type, and nominal value.
+#
+# Components that are not contained in the BOM are deactivated in the
+# simulation model.
+# This example saves the CSV file in the ``aedb`` folder.
#
+# ```
# +------------+-----------------------+-----------+------------+
# | RefDes | Part name | Type | Value |
# +============+=======================+===========+============+
# | C380 | CAPC1005X55X25LL05T10 | Capacitor | 11nF |
# +------------+-----------------------+-----------+------------+
-
+# ```
+#
+# Having red the informaton in the BOM and definitions file, electrical models can be
+# assigned to all of the components in the simulation model.
edbapp.components.import_bom(os.path.join(target_aedb, "0_bom.csv"),
refdes_col=0,
@@ -97,38 +98,33 @@
comp_type_col=2,
value_col=3)
-
-
-###############################################################################
-# Check Component Values
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Verify a Component
+#
# Component property allows to access all components instances and their property with getters and setters.
comp = edbapp.components["C1"]
comp.model_type, comp.value
-
-###############################################################################
-# Check Component Definition
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Check component definition
+#
# When an s-parameter model is associated to a component it will be available in nport_comp_definition property.
edbapp.components.nport_comp_definition
-
-###############################################################################
-# Save Edb
-# ~~~~~~~~
edbapp.save_edb()
-###############################################################################
-# Configure Setup
-# ~~~~~~~~~~~~~~~
-# This step allows to define the project. It includes:
-# - Definition of nets to be included into the cutout,
-# - Cutout details,
-# - Components on which to create the ports,
-# - Simulation settings.
+# ## Configure the simulation setup
+#
+# This step enables the following:
+# - Definition of the nets to include in the cutout region
+# - Cutout details
+# - Components to create the ports on
+# - Simulation settings
+#
+# The ``Edb.new_simulaton_configuration()`` method returns an instance
+# of the [``SimulationConfiguration``](https://aedt.docs.pyansys.com/version/stable/EDBAPI/SimulationConfigurationEdb.html) class.
+
+# +
sim_setup = edbapp.new_simulation_configuration()
sim_setup.solver_type = sim_setup.SOLVER_TYPE.SiwaveSYZ
sim_setup.batch_solve_settings.cutout_subdesign_expansion = 0.003
@@ -146,57 +142,66 @@
sim_setup.ac_settings.start_freq = "100Hz"
sim_setup.ac_settings.stop_freq = "6GHz"
sim_setup.ac_settings.step_freq = "10MHz"
+# -
-###############################################################################
-# Run Setup
-# ~~~~~~~~~
-# This step allows to create the cutout and apply all settings.
+# ## Implement the setup
+#
+# The cutout and all other simulation settings are applied to the simulation model.
-sim_setup.export_json(os.path.join(project_path, "configuration.json"))
+sim_setup.export_json(os.path.join(temp_dir.name, "configuration.json"))
edbapp.build_simulation_project(sim_setup)
-###############################################################################
-# Plot Cutout
-# ~~~~~~~~~~~
-# Plot cutout once finished.
+# ## Display the cutout
+#
+# Plot cutout once finished. The model is ready to simulate.
edbapp.nets.plot(None,None)
-###############################################################################
-# Save and Close EDB
-# ~~~~~~~~~~~~~~~~~~
-# Edb will be saved and closed in order to be opened by Hfss 3D Layout and solved.
+# ## Save and close EDB
+#
+# EDB is saved and re-opened in HFSS
+# 3D Layout, where the HFSS simulation can be run.
edbapp.save_edb()
edbapp.close_edb()
-###############################################################################
-# Open Aedt
-# ~~~~~~~~~
-# Project folder aedb will be opened in AEDT Hfss3DLayout and loaded.
-h3d = pyaedt.Hfss3dLayout(specified_version="2023.2", projectname=target_aedb, non_graphical=non_graphical, new_desktop_session=True)
+# ## Open Electronics Desktop
+#
+# The EDB is opened in AEDT Hfss3DLayout.
+#
+# Set ``non_graphical=True`` to run the simulation in non-graphical mode.
+
+h3d = pyaedt.Hfss3dLayout(specified_version="2023.2",
+ projectname=target_aedb,
+ non_graphical=False,
+ new_desktop_session=False)
+
+# ## Analyze
+#
+# This project is ready to solve. Executing the following cell runs the HFSS simulation on the layout.
-###############################################################################
-# Analyze
-# ~~~~~~~
-# Project will be solved.
h3d.analyze()
-###############################################################################
-# Get Results
-# ~~~~~~~~~~~
-# S Parameter data will be loaded at the end of simulation.
+# ## View results
+#
+# S-parameter data is loaded at the end of simulation.
+
solutions = h3d.post.get_solution_data()
-###############################################################################
-# Plot Results
-# ~~~~~~~~~~~~
-# Plot S Parameter data.
+# ## Plot results
+#
+# Plot S-Parameter data.
+
solutions.plot(solutions.expressions, "db20")
-###############################################################################
-# Save and Close AEDT
-# ~~~~~~~~~~~~~~~~~~~
-# Hfss3dLayout is saved and closed.
+# ## Save and close AEDT
+#
+# HFSS 3D Layout is saved and closed.
+
h3d.save_project()
h3d.release_desktop()
+
+# Clean up the temporary directory. All files and the temporary project
+# folder will be deleted in the next step.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/10_GDS_workflow.py b/examples/00-EDB/10_GDS_workflow.py
index 091e289c5e7..7215dc6fdd7 100644
--- a/examples/00-EDB/10_GDS_workflow.py
+++ b/examples/00-EDB/10_GDS_workflow.py
@@ -1,13 +1,9 @@
-"""
-EDB: Edit Control File and import gds
--------------------------------------
-This example shows how you can use PyAEDT to import a gds from an IC file.
-"""
+# # EDB: Edit Control File and import gds
+#
+# This example demonstrates how to import a gds layout for subsequent
+# simulation with HFSS.
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports, which includes importing a section.
+# Perform imports.
import os
import tempfile
@@ -15,22 +11,32 @@
import shutil
from pyaedt.edb_core.edb_data.control_file import ControlFile
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
-# Download the AEDB file and copy it in the temporary folder.
-temppath = tempfile.gettempdir()
-local_path = pyaedt.downloads.download_file('gds')
-c_file_in = os.path.join(
- local_path, "sky130_fictitious_dtc_example_control_no_map.xml"
-)
-c_map = os.path.join(local_path, "dummy_layermap.map")
-gds_in = os.path.join(local_path, "sky130_fictitious_dtc_example.gds")
-gds_out = os.path.join(temppath, "example.gds")
+# ## Fetch Example Data
+#
+# Download the EDB folder and copy it to a temporary folder.
+# The following files are used in this example:
+# - _sky130_fictious_dtc_exmple_contol_no_map.xml_
+# defines physical information such
+# as material properties, stackup layers, and boundary conditions.
+# - _dummy_layermap.map_
+# maps properties to stackup layers.
+
+# +
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+control_fn = "sky130_fictitious_dtc_example_control_no_map.xml"
+gds_fn = "sky130_fictitious_dtc_example.gds"
+layer_map = "dummy_layermap.map"
+
+local_path = pyaedt.downloads.download_file('gds', destination=temp_dir.name)
+c_file_in = os.path.join(local_path, control_fn)
+c_map = os.path.join(local_path, layer_map)
+gds_in = os.path.join(local_path, gds_fn)
+gds_out = os.path.join(temp_dir, "gds_out.gds")
shutil.copy2(gds_in,gds_out )
-###############################################################################
-# Control file
-# ~~~~~~~~~~~~
+# -
+
+# ## Control file
+#
# A Control file is an xml file which purpose if to provide additional
# information during import phase. It can include, materials, stackup, setup, boundaries and settings.
# In this example we will import an existing xml, integrate it with a layer mapping file of gds
@@ -38,18 +44,17 @@
c = ControlFile(c_file_in, layer_map=c_map)
+# ## Set up simulation
+#
+# This code sets up a simulation with HFSS and adds a frequency sweep.
-###############################################################################
-# Simulation setup
-# ~~~~~~~~~~~~~~~~
-# Here we setup simulation with HFSS and add a frequency sweep.
setup = c.setups.add_setup("Setup1", "1GHz")
setup.add_sweep("Sweep1", "0.01GHz", "5GHz", "0.1GHz")
-###############################################################################
-# Additional stackup settings
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# After import user can change stackup settings and add/remove layers or materials.
+# ## Provide additional stackup settings
+#
+# After import, you can change the stackup settings and add or remove layers or materials.
+
c.stackup.units = "um"
c.stackup.dielectrics_base_elevation = -100
c.stackup.metal_layer_snapping_tolerance = "10nm"
@@ -57,14 +62,13 @@
via.create_via_group = True
via.snap_via_group = True
-
-###############################################################################
-# Boundaries settings
-# ~~~~~~~~~~~~~~~~~~~
+# ## Define boundary settings
+#
# Boundaries can include ports, components and boundary extent.
c.boundaries.units = "um"
-c.boundaries.add_port("P1", x1=223.7, y1=222.6, layer1="Metal6", x2=223.7, y2=100, layer2="Metal6")
+c.boundaries.add_port("P1", x1=223.7, y1=222.6, layer1="Metal6",
+ x2=223.7, y2=100, layer2="Metal6")
c.boundaries.add_extent()
comp = c.components.add_component("B1", "BGA", "IC", "Flip chip", "Cylinder")
comp.solder_diameter = "65um"
@@ -74,31 +78,35 @@
comp.add_pin("4", "81.28", "214.6", "met2")
c.import_options.import_dummy_nets = True
-###############################################################################
-# Write xml
-# ~~~~~~~~~
-# After all settings are ready we can write xml.
+# ## Write XML file
+#
+# After all settings are ready, you can write an XML file.
-c.write_xml(os.path.join(temppath, "output.xml"))
+c.write_xml(os.path.join(temp_dir.name, "output.xml"))
-###############################################################################
-# Open Edb
-# ~~~~~~~~~
+# ## Open EDB
+#
# Import the gds and open the edb.
+# +
from pyaedt import Edb
-edb = Edb(gds_out, edbversion="2023.2", technology_file=os.path.join(temppath, "output.xml"))
+edb = Edb(gds_out, edbversion="2023.2",
+ technology_file=os.path.join(temp_dir.name, "output.xml"))
+# -
+
+# ## Plot stackup
+#
+# Plot the stackup.
-###############################################################################
-# Plot Stackup
-# ~~~~~~~~~~~~
-# Stackup plot.
edb.stackup.plot(first_layer="met1")
-###############################################################################
-# Close Edb
-# ~~~~~~~~~
+# ## Close EDB
+#
# Close the project.
-edb.close_edb()
\ No newline at end of file
+edb.close_edb()
+
+# Clean up the temporary folder.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/11_post_layout_parameterization.py b/examples/00-EDB/11_post_layout_parameterization.py
index 4925a6e4217..34a019edc82 100644
--- a/examples/00-EDB/11_post_layout_parameterization.py
+++ b/examples/00-EDB/11_post_layout_parameterization.py
@@ -1,44 +1,39 @@
-"""
-EDB: post-layout parameterization
----------------------------------
-This example shows you how to parameterize the signal net in post-layout.
-"""
-
-###############################################################################
-# Define input parameters
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: post-layout parameterization
+#
+# This example shows you how to parameterize the signal net in post-layout.
+#
+# Define input parameters.
+
signal_net_name = "DDR4_ALERT3"
-coplanar_plane_net_name = "1V0" # Specify coplanar plane net name for adding clearance
-layers = ["16_Bottom"] # Specify layers to be parameterized
+coplanar_plane_net_name = "1V0" # Specify name of coplanar plane net for adding clearance
+layers = ["16_Bottom"] # Specify layers to parameterize
+
+# Perform required imports.
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
import os
import tempfile
import pyaedt
-from pyaedt import downloads
-from pyaedt import Edb
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+
+# Download and open example layout file in edb format.
-temppath = pyaedt.generate_unique_folder_name()
+edb_path = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',
+ destination=temp_dir.name)
+edb = pyaedt.Edb(edb_path, edbversion="2023.2")
-###############################################################################
-# Download and open example layout file in edb format
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-edb_fpath = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',destination=temppath)
-appedb = Edb(edb_fpath, edbversion="2023.2")
+# ## Create cutout
+#
+# The ``Edb.cutout()`` method takes a list of
+# signal nets as the first argument and a list of
+# reference nets as the second argument.
-###############################################################################
-# Cutout
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-appedb.cutout([signal_net_name], [coplanar_plane_net_name, "GND"],
+edb.cutout([signal_net_name], [coplanar_plane_net_name, "GND"],
remove_single_pin_components=True)
-###############################################################################
-# Get all trace segments from the signal net
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-net = appedb.nets[signal_net_name]
+# Retrieve the path segments from the signal net.
+
+net = edb.nets[signal_net_name]
trace_segments = []
for p in net.primitives:
if p.layer_name not in layers:
@@ -47,47 +42,47 @@
continue
trace_segments.append(p)
-###############################################################################
-# Create and assign delta w variable per layer
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create and assign delta w variable per layer.
+
for p in trace_segments:
vname = f"{p.net_name}_{p.layer_name}_dw"
- if vname not in appedb.variables:
- appedb[vname] = "0mm"
+ if vname not in edb.variables:
+ edb[vname] = "0mm"
new_w = f"{p.width}+{vname}"
p.width = new_w
-###############################################################################
-# Delete existing clearance
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Delete existing clearance.
+
for p in trace_segments:
- for g in appedb.modeler.get_polygons_by_layer(p.layer_name, coplanar_plane_net_name):
+ for g in edb.modeler.get_polygons_by_layer(p.layer_name,
+ coplanar_plane_net_name):
for v in g.voids:
if p.is_intersecting(v):
v.delete()
-###############################################################################
-# Create and assign clearance variable per layer
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create and assign the clearance variable for each layer.
+
for p in trace_segments:
clr = f"{p.net_name}_{p.layer_name}_clr"
- if clr not in appedb.variables:
- appedb[clr] = "0.5mm"
+ if clr not in edb.variables:
+ edb[clr] = "0.5mm"
path = p.get_center_line()
- for g in appedb.modeler.get_polygons_by_layer(p.layer_name, coplanar_plane_net_name):
- void = appedb.modeler.create_trace(path, p.layer_name, f"{p.width}+{clr}*2")
+ for g in edb.modeler.get_polygons_by_layer(p.layer_name,
+ coplanar_plane_net_name):
+ void = edb.modeler.create_trace(path, p.layer_name, f"{p.width}+{clr}*2")
g.add_void(void)
-###############################################################################
-# Plot
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-appedb.nets.plot(layers=layers[0], size=2000)
+# Visualize the layout.
+
+edb.nets.plot(layers=layers[0], size=2000)
+
+# Save the AEDB file and close EDB.
+
+save_edb_path = os.path.join(temp_dir.name, "post_layout_parameterization.aedb")
+edb.save_edb_as(save_edb_path)
+print("Edb is saved to ", save_edb_path)
+edb.close_edb()
-###############################################################################
-# Save and close Edb
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Clean up the temporary folder.
-save_edb_fpath = os.path.join(temppath, pyaedt.generate_unique_name("post_layout_parameterization") + ".aedb")
-appedb.save_edb_as(save_edb_fpath)
-print("Edb is saved to ", save_edb_fpath)
-appedb.close_edb()
+temp_dir.cleanup()
\ No newline at end of file
diff --git a/examples/00-EDB/12_edb_sma_connector_on_board.py b/examples/00-EDB/12_edb_sma_connector_on_board.py
index ee73e020f51..e590988f7bc 100644
--- a/examples/00-EDB/12_edb_sma_connector_on_board.py
+++ b/examples/00-EDB/12_edb_sma_connector_on_board.py
@@ -1,49 +1,46 @@
-"""
-EDB: geometry creation
-----------------------
-This example shows how to
-1, Create a parameterized PCB layout design.
-2, Place 3D component on PCB.
-3, Create HFSS setup and frequency sweep with a mesh operation.
-4, Create return loss plot
-"""
-######################################################################
+# # EDB: geometry creation
#
-# Final expected project
-# ~~~~~~~~~~~~~~~~~~~~~~
+# This example shows how to
+# 1. Create a parameterized PCB with an SMA connector footprint for a single-ended
+# SMA connector launch footprint..
+# 2. Place 3D component on PCB.
+# 3. Create HFSS setup and frequency sweep with a mesh operation.
+# 4. Create return loss plot
+
+# ## See the finished project
#
-# .. image:: ../../_static/edb_example_12_sma_connector_on_board.png
-# :width: 600
-# :alt: Differential Vias.
-######################################################################
+#
-######################################################################
-# Create parameterized PCB
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Initialize an empty EDB layout object on version 2023 R2.
-######################################################################
+# ## Create a parameterized PCB
+#
+# Import dependencies.
import os
import numpy as np
import pyaedt
+import tempfile
+
+# Create the EDB.
+# +
ansys_version = "2023.2"
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+working_folder = temp_dir.name
-aedb_path = os.path.join(pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("pcb") + ".aedb")
+aedb_path = os.path.join(working_folder, "pcb.aedb")
edb = pyaedt.Edb(edbpath=aedb_path, edbversion=ansys_version)
-print("EDB is located at {}".format(aedb_path))
+print("AEDB file is located in {}".format(aedb_path))
+# -
-#####################
-# Create FR4 material
-# ~~~~~~~~~~~~~~~~~~~
+# Add the FR4 dielectric for the PCB.
edb.materials.add_dielectric_material("ANSYS_FR4", 3.5, 0.005)
-################
-# Create stackup
-# ~~~~~~~~~~~~~~
-# A stackup can be created by importing from a csv/xml file or adding layer by layer.
+# ## Create Stackup
#
+# While this code explicitly defines the stackup, you can import it
+# from a from a CSV or XML file using the
+# ``Edb.stackup.import_stackup()`` method.
edb.add_design_variable("$DIEL_T", "0.15mm")
edb.stackup.add_layer("BOT")
@@ -58,23 +55,22 @@
edb.stackup.add_layer("D1", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4")
edb.stackup.add_layer("TOP", "Diel", thickness="0.05mm")
-######################
-# Create ground planes
-# ~~~~~~~~~~~~~~~~~~~~
-#
+# Create ground conductors.
+# +
edb.add_design_variable("PCB_W", "20mm")
edb.add_design_variable("PCB_L", "20mm")
gnd_dict = {}
for layer_name in edb.stackup.signal_layers.keys():
gnd_dict[layer_name] = edb.modeler.create_rectangle(layer_name, "GND", [0, "PCB_W/-2"], ["PCB_L", "PCB_W/2"])
+# -
-###################
-# Create signal net
-# ~~~~~~~~~~~~~~~~~
+# ## Create signal net
+#
# Create signal net on layer 3, and add clearance to the ground plane.
+# +
edb.add_design_variable("SIG_L", "10mm")
edb.add_design_variable("SIG_W", "0.1mm")
edb.add_design_variable("SIG_C", "0.3mm")
@@ -85,114 +81,116 @@
signal_path = (["5mm", 0], ["PCB_L", 0])
clr = edb.modeler.create_trace(signal_path, "L3", "SIG_C*2+SIG_W", "SIG", "Flat", "Flat")
gnd_dict["L3"].add_void(clr)
+# -
-####################
-# Create signal vias
-# ~~~~~~~~~~~~~~~~~~
-# Create via padstack definition. Place the signal vias.
+# ## Place signal vias
+#
+# Create the via padstack definition and place the signal vias.
edb.add_design_variable("SG_VIA_D", "1mm")
-
edb.add_design_variable("$VIA_AP_D", "1.2mm")
-
edb.padstacks.create("ANSYS_VIA", "0.3mm", "0.5mm", "$VIA_AP_D")
-
edb.padstacks.place(["5mm", 0], "ANSYS_VIA", "SIG")
-######################################
-# Create ground vias around signal via
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create ground vias around the SMA
+# connector launch footprint. The vias
+# are placed around the circumference
+# of the launch from 35 degrees to 325
+# degrees.
-for i in np.arange(30, 331, 30):
+for i in np.arange(30, 326, 35):
px = np.cos(i / 180 * np.pi)
py = np.sin(i / 180 * np.pi)
edb.padstacks.place(["{}*{}+5mm".format("SG_VIA_D", px), "{}*{}".format("SG_VIA_D", py)], "ANSYS_VIA", "GND")
-#######################################
-# Create ground vias along signal trace
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create ground vias along the signal trace.
for i in np.arange(2e-3, edb.variables["SIG_L"].value - 2e-3, 2e-3):
edb.padstacks.place(["{}+5mm".format(i), "1mm"], "ANSYS_VIA", "GND")
edb.padstacks.place(["{}+5mm".format(i), "-1mm"], "ANSYS_VIA", "GND")
-###################################################
-# Create a wave port at the end of the signal trace
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create a wave port at the end of the signal trace.
signal_trace.create_edge_port("port_1", "End", "Wave", horizontal_extent_factor=10)
-##################
-# Set hfss options
-# ~~~~~~~~~~~~~~~~
+# ## Set up HFSS simulation
+#
+# The ``max_num_passes`` argument sets an upper limit on the
+# number of adaptive passes for mesh refinement.
+#
+# For broadband applications when the simulation results may be used
+# to generate a SPICE model, the outer domain boundary can be
+# located roughly $$ d=\lambda/8 $$ from the internal structures
+# in the model.
+# +
+extend_domain = 3E11/5E9/8.0 # Quarter wavelength at 4 GHz.
edb.design_options.antipads_always_on = True
-edb.hfss.hfss_extent_info.air_box_horizontal_extent = 0.01
-edb.hfss.hfss_extent_info.air_box_positive_vertical_extent = 2
-edb.hfss.hfss_extent_info.air_box_negative_vertical_extent = 2
-
-##############
-# Create setup
-# ~~~~~~~~~~~~
+edb.hfss.hfss_extent_info.air_box_horizontal_extent = extend_domain
+edb.hfss.hfss_extent_info.air_box_positive_vertical_extent = extend_domain
+edb.hfss.hfss_extent_info.air_box_negative_vertical_extent = extend_domain
setup = edb.create_hfss_setup("Setup1")
-setup.set_solution_single_frequency("5GHz", max_num_passes=2, max_delta_s="0.01")
+setup.set_solution_single_frequency("5GHz", max_num_passes=8, max_delta_s="0.02")
setup.hfss_solver_settings.order_basis = "first"
+# -
+
+# Add a mesh operation to the setup.
-#############################
-# Add mesh operation to setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
edb.setups["Setup1"].add_length_mesh_operation({"SIG": ["L3"]}, "m1", max_length="0.1mm")
-##############################
-# Add frequency sweep to setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Add a frequency sweep to setup.
+#
+# When the simulation results are to
+# be used for transient SPICE analysis, you should
+# use the following strategy:
+#
+# - DC point
+# - Logarithmic sweep from 1 kHz to 100 MHz
+# - Linear scale for higher frequencies.
setup.add_frequency_sweep(
"Sweep1",
frequency_sweep=[
["linear count", "0", "1KHz", 1],
- ["log scale", "1KHz", "0.1GHz", 10],
+ ["log scale", "1KHz", "100MHz", 10],
["linear scale", "0.1GHz", "5GHz", "0.1GHz"],
],
)
-####################
-# Save and close EDB
-# ~~~~~~~~~~~~~~~~~~
+# Save and close EDB.
edb.save_edb()
edb.close_edb()
-#####################
-# Launch Hfss3dLayout
-# ~~~~~~~~~~~~~~~~~~~
+# Launch HFSS 3D Layout.
h3d = pyaedt.Hfss3dLayout(aedb_path, specified_version=ansys_version, new_desktop_session=True)
-####################
-# Place 3D component
-# ~~~~~~~~~~~~~~~~~~
-
-component3d = pyaedt.downloads.download_file("component_3d", "SMA_RF_SURFACE_MOUNT.a3dcomp",)
+# Place a 3D component.
+full_comp_name = pyaedt.downloads.download_file("component_3d",
+ filename="SMA_RF_SURFACE_MOUNT.a3dcomp",
+ destination=working_folder)
comp = h3d.modeler.place_3d_component(
- component_path=component3d, number_of_terminals=1, placement_layer="TOP", component_name="my_connector",
+ component_path=full_comp_name, number_of_terminals=1,
+ placement_layer="TOP", component_name="my_connector",
pos_x="5mm", pos_y=0.000)
-##########
-# Analysis
-# ~~~~~~~~
+# ## Run simulation
+
h3d.analyze(num_cores=4)
-#########################
-# Create return loss plot
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Visualize the return loss.
+
h3d.post.create_report("dB(S(port_1, port_1))")
-############################
-# Save and close the project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save and close the project.
+
h3d.save_project()
print("Project is saved to {}".format(h3d.project_path))
h3d.release_desktop(True, True)
+
+# ## Clean up the temporary folder.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/13_edb_create_component.py b/examples/00-EDB/13_edb_create_component.py
index 9c3571e4e7a..7f7c6916a81 100644
--- a/examples/00-EDB/13_edb_create_component.py
+++ b/examples/00-EDB/13_edb_create_component.py
@@ -1,44 +1,43 @@
-"""
-EDB: geometry creation
-----------------------
-This example shows how to
-1, Create a layout layer stackup.
-2, Create Padstack definition.
-3, Place padstack instances at given location.
-4, Create primitives, polygon and trace.
-5, Create component from pins.
-6, Create HFSS simulation setup and excitation ports.
-"""
-######################################################################
+# # EDB: Layout Creation and Setup
#
-# Final expected project
-# ~~~~~~~~~~~~~~~~~~~~~~
+# This example demonstrates how to to
#
-# .. image:: ../../_static/connector_example.png
-# :width: 600
-# :alt: Connector from Vias.
-######################################################################
+# 1. Create a layout layer stackup.
+# 2. Define padstacks.
+# 3. Place padstack instances in the layout where the connectors are located.
+# 4. Create primitives such as polygons and traces.
+# 5. Create "components" from the padstack definitions using "pins".
+# >The "component" in EDB acts as a placeholder to enable automatic
+# >placement of electrical models, or
+# >as in this example to assign ports. In many
+# >cases the EDB is imported from a 3rd party layout, in which case the
+# >concept of a "component" as a placeholder is needed to map
+# >models to the components on the PCB for later use in the
+# >simulation.
+# 7. Create the HFSS simulation setup and assign ports where the connectors are located.
+
+# ## View PCB trace model
+#
+# Here is an image of the model that is created in this example.
+#
+#
+#
+# The rectangular sheets at each end of the PCB enable placement of ports where the connectors are located.
-######################################################################
-# Create connector component from pad-stack
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Initialize an empty EDB layout object on version 2023 R2.
-######################################################################
+# Initialize the EDB layout object.
import os
import pyaedt
+import tempfile
from pyaedt import Edb
-aedb_path = os.path.join(pyaedt.generate_unique_folder_name(),
- pyaedt.generate_unique_name("component_example") + ".aedb")
-
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+aedb_path = os.path.join(temp_dir.name, "component_example.aedb")
edb = Edb(edbpath=aedb_path, edbversion="2023.2")
print("EDB is located at {}".format(aedb_path))
-######################
# Initialize variables
-# ~~~~~~~~~~~~~~~~~~~~
layout_count = 12
diel_material_name = "FR4_epoxy"
@@ -52,18 +51,14 @@
connector_size = 2e-3
conectors_position = [[0, 0], [10e-3, 0]]
-################
-# Create stackup
-# ~~~~~~~~~~~~~~
+# Create the stackup
+
edb.stackup.create_symmetric_stackup(layer_count=layout_count, inner_layer_thickness=cond_thickness_inner,
outer_layer_thickness=cond_thickness_outer,
soldermask_thickness=soldermask_thickness, dielectric_thickness=diel_thickness,
dielectric_material=diel_material_name)
-######################
# Create ground planes
-# ~~~~~~~~~~~~~~~~~~~~
-#
ground_layers = [layer_name for layer_name in edb.stackup.signal_layers.keys() if layer_name not in
[trace_in_layer, trace_out_layer]]
@@ -71,9 +66,13 @@
for i in ground_layers:
edb.modeler.create_polygon(plane_shape, i, net_name="VSS")
-######################
-# Add design variables
-# ~~~~~~~~~~~~~~~~~~~~
+# ### Add design parameters
+#
+# Parameters that are preceeded by a _"$"_ character have project-wide scope.
+# Therefore, the padstack **definition** and hence all instances of that padstack rely on the parameters.
+#
+# Parameters such as _"trace_in_width"_ and _"trace_out_width"_ have local scope and
+# are only used in in the design.
edb.add_design_variable("$via_hole_size", "0.3mm")
edb.add_design_variable("$antipaddiam", "0.7mm")
@@ -81,16 +80,14 @@
edb.add_design_variable("trace_in_width", "0.2mm", is_parameter=True)
edb.add_design_variable("trace_out_width", "0.1mm", is_parameter=True)
-############################
-# Create padstack definition
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Create the connector component
+#
+# The component definition is used to place the connector on the PCB. First define the padstacks.
edb.padstacks.create_padstack(padstackname="Via", holediam="$via_hole_size", antipaddiam="$antipaddiam",
paddiam="$paddiam")
-####################
-# Create connector 1
-# ~~~~~~~~~~~~~~~~~~
+# Create the first connector
component1_pins = [edb.padstacks.place_padstack(conectors_position[0], "Via", net_name="VDD", fromlayer=trace_in_layer,
tolayer=trace_out_layer),
@@ -107,9 +104,7 @@
conectors_position[0][1] + connector_size / 2],
"Via", net_name="VSS")]
-####################
-# Create connector 2
-# ~~~~~~~~~~~~~~~~~~
+# Create the second connector
component2_pins = [
edb.padstacks.place_padstack(conectors_position[-1], "Via", net_name="VDD", fromlayer=trace_in_layer,
@@ -127,23 +122,20 @@
conectors_position[1][1] + connector_size / 2],
"Via", net_name="VSS")]
-####################
-# Create layout pins
-# ~~~~~~~~~~~~~~~~~~
+# ### Define pins
+#
+# Pins are fist defined to allow a component to subsequently connect to the remainder
+# of the model. In this case, ports are assigned at the connector instances using the pins.
for padstack_instance in list(edb.padstacks.instances.values()):
padstack_instance.is_pin = True
-############################
-# create component from pins
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create components from the pins
edb.components.create(component1_pins, 'connector_1')
edb.components.create(component2_pins, 'connector_2')
-################################################################################
-# Creating ports and adding simulation setup using SimulationConfiguration class
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Create ports on the pins and insert a simulation setup using the ``SimulationConfiguration`` class.
sim_setup = edb.new_simulation_configuration()
sim_setup.solver_type = sim_setup.SOLVER_TYPE.Hfss3dLayout
@@ -157,14 +149,31 @@
sim_setup.ac_settings.step_freq = "1GHz"
edb.build_simulation_project(sim_setup)
-###########################
-# Save EDB and open in AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# Save the EDB and open it in the 3D Layout editor. If ``non_graphical==False``,
+# there may be a delay while AEDT starts.
edb.save_edb()
edb.close_edb()
h3d = pyaedt.Hfss3dLayout(specified_version="2023.2",
projectname=aedb_path,
- non_graphical=False,
+ non_graphical=False, # Set non_graphical = False to launch AEDT in graphical mode.
new_desktop_session=True)
-h3d.release_desktop(False, False)
+
+# ### Release the application from the Python kernel
+#
+# It is important to release the application from the Python kernel after
+# execution of the script. The default behavior of the ``release_desktop()`` method closes all open
+# projects and closes the application.
+#
+# If you want to conintue working on the project in graphical mode
+# after script execution, call the following method with both arguments set to ``False``.
+
+h3d.release_desktop(close_projects=True, close_desktop=True)
+
+# ### Clean up the temporary directory
+#
+# The following command cleans up the temporary directory, thereby removing all
+# project files. If you'd like to save this project, save it to a folder of your choice
+# prior to running the following cell.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/14_edb_create_parametrized_design.py b/examples/00-EDB/14_edb_create_parametrized_design.py
index d4cf224f299..0e5b7740711 100644
--- a/examples/00-EDB/14_edb_create_parametrized_design.py
+++ b/examples/00-EDB/14_edb_create_parametrized_design.py
@@ -1,40 +1,39 @@
-"""
-EDB: parameterized design
-------------------------
-This example shows how to
-1, Create an HFSS simulation project using SimulationConfiguration class.
-2, Create automatically parametrized design.
-"""
-######################################################################
+# # EDB: parameterized design
+#
+# This example shows how to
+# 1. Set up an HFSS project using SimulationConfiguration class.
+# 2. Create automatically parametrized design.
+#
+# This image shows the layout created in this example:
+#
+#
#
-# Final expected project
-# ~~~~~~~~~~~~~~~~~~~~~~
#
-# .. image:: ../../_static/parametrized_design.png
-# :width: 600
-# :alt: Fully automated parametrization.
-######################################################################
-######################################################################
-# Create HFSS simulatio project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Load an existing EDB folder.
-######################################################################
+# Import dependencies.
import os
import pyaedt
+import tempfile
+
+# Create an instance of a pyaedt.Edb object.
-project_path = pyaedt.generate_unique_folder_name()
-target_aedb = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=project_path)
-print("Project folder will be", target_aedb)
+# +
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+target_aedb = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_dir.name)
+print("Project is located in ", target_aedb)
aedt_version = "2023.2"
edb = pyaedt.Edb(edbpath=target_aedb, edbversion=aedt_version)
-print("EDB is located at {}".format(target_aedb))
+print("AEDB file is located in {}".format(target_aedb))
+# -
-########################################################################
-# Create SimulationConfiguration object and define simulation parameters
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Prepare the layout for the simulation
+#
+# The ``new_simulation_configuration()`` method creates an instance of
+# the ``SimulationConfiguration`` class. This class helps define all preprocessing steps
+# required to set up the PCB for simulation. After the simulation configuration has been defined,
+# they are applied to the EDB using the ``Edb.build_simulation()`` method.
simulation_configuration = edb.new_simulation_configuration()
simulation_configuration.signal_nets = ["PCIe_Gen4_RX0_P", "PCIe_Gen4_RX0_N",
@@ -46,24 +45,57 @@
simulation_configuration.stop_freq = "20GHz"
simulation_configuration.step_freq = "10MHz"
-##########################
-# Build simulation project
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# Now apply the simulation setup to the EDB.
edb.build_simulation_project(simulation_configuration)
-#############################
-# Generated design parameters
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Parameterize
+#
+# The layout can automatically be set up to enable parametric studies. For example, the
+# impact of antipad diameter or trace width on signal integrity performance may be invested parametrically.
edb.auto_parametrize_design(layers=True, materials=True, via_holes=True, pads=True, antipads=True, traces=True)
edb.save_edb()
edb.close_edb()
-######################
-# Open project in AEDT
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Open project in AEDT
+#
+# All manipulations thus far have been executed using the EDB API, which provides fast, streamlined processing of
+# layout data in non-graphical mode. The layout and simulation setup can be visualized by opening it using the
+# 3D Layout editor in AEDT.
+#
+# Note that there may be some delay while AEDT is being launched.
+
+hfss = pyaedt.Hfss3dLayout(projectname=target_aedb,
+ specified_version=aedt_version,
+ non_graphical=False,
+ new_desktop_session=True)
+
+# The following cell can be used to ensure that the design is valid for simulation.
+
+validation_info = hfss.validate_full_design()
+is_ready_to_simulate = True
+
+# +
+for s in validation_info[0]:
+ if "error" in s:
+ print(s)
+ is_ready_to_simulate = False
+
+if is_ready_to_simulate:
+ print("The model is ready for simulation.")
+else:
+ print("There are errors in the model that must be fixed.")
+# -
+
+# ### Release the application from the Python kernel
+#
+# It is important to release the application from the Python kernel after
+# execution of the script. The default behavior of the ``release_desktop()`` method closes all open
+# projects and closes the application.
+#
+# If you want to continue working on the project in graphical mode
+# after script execution, call the following method with both arguments set to ``False``.
-# Uncomment the following line to open the design in HFSS 3D Layout
-# hfss = pyaedt.Hfss3dLayout(projectname=target_aedb, specified_version=aedt_version, new_desktop_session=True)
-# hfss.release_desktop()
+hfss.release_desktop(close_projects=True, close_desktop=True)
+temp_dir.cleanup() # Remove the temporary folder and files. All data will be removd!
diff --git a/examples/00-EDB/15_ac_analysis.py b/examples/00-EDB/15_ac_analysis.py
index 557d2554cd2..4b65f352459 100644
--- a/examples/00-EDB/15_ac_analysis.py
+++ b/examples/00-EDB/15_ac_analysis.py
@@ -1,51 +1,50 @@
-"""
-EDB: SYZ analysis
--------------------
-This example shows how you can use PyAEDT to set up SYZ analysis on Serdes channel.
-The input is the name of the differential nets. The positive net is PCIe_Gen4_TX3_CAP_P.
-The negative net is PCIe_Gen4_TX3_CAP_N. The code will place ports on driver and
-receiver components.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EDB: Network Analysis in SIwave
+#
+# This example shows how to use PyAEDT to set up SYZ analysis on a
+# [serdes](https://en.wikipedia.org/wiki/SerDes) channel.
+# The signal input is applied differetially. The positive net is _"PCIe_Gen4_TX3_CAP_P"_.
+# The negative net is _"PCIe_Gen4_TX3_CAP_N"_. In this example, ports are placed on the
+# driver and
+# receiver components.
+
+# ### Perform required imports
+#
# Perform required imports, which includes importing a section.
import time
import pyaedt
+import tempfile
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
+# ### Download file
+#
# Download the AEDB file and copy it in the temporary folder.
-temp_folder = pyaedt.generate_unique_folder_name()
-targetfile = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_folder)
+# +
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+edb_full_path = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=temp_dir.name)
time.sleep(5)
-print(targetfile)
+print(edb_full_path)
+# -
-###############################################################################
-# Configure EDB
-# ~~~~~~~~~~~~~
-# Launch the :class:`pyaedt.Edb` class, using EDB 2023 R2.
+# ### Configure EDB
+#
+# Create an instance of the ``pyaedt.Edb`` class.
-edbapp = pyaedt.Edb(edbpath=targetfile, edbversion="2023.2")
+edbapp = pyaedt.Edb(edbpath=edb_full_path, edbversion="2023.2")
-###############################################################################
-# Generate extended nets
-# ~~~~~~~~~~~~~~~~~~~~~~
-# An extended net is a connection between two nets that are usually connected
-# through a passive component like a resistor or capacitor.
+# ### Generate extended nets
+#
+# An extended net consists of two nets that are connected
+# through a passive component such as a resistor or capacitor.
-edbapp.extended_nets.auto_identify_signal(resistor_below=10, inductor_below=1, capacitor_above=1e-9)
+all_nets = edbapp.extended_nets.auto_identify_signal(resistor_below=10,
+ inductor_below=1,
+ capacitor_above=1e-9)
-###############################################################################
-# Review extended net properties
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Review extended net properties.
+# Review the properties of extended nets.
+# +
diff_p = edbapp.nets["PCIe_Gen4_TX3_CAP_P"]
diff_n = edbapp.nets["PCIe_Gen4_TX3_CAP_N"]
@@ -59,12 +58,11 @@
rlc_n = list(diff_n.extended_net.rlc.keys())
print(comp_p, rlc_p, comp_n, rlc_n, sep="\n")
+# -
-###############################################################################
-# Prepare input data for port creation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Prepare input data for port creation.
+# +
ports = []
for net_name, net_obj in diff_p.extended_net.nets.items():
for comp_name, comp_obj in net_obj.components.items():
@@ -81,10 +79,10 @@
"net_name":net_name})
print(*ports, sep="\n")
+# -
-###############################################################################
-# Create ports
-# ~~~~~~~~~~~~
+# ### Create ports
+#
# Solder balls are generated automatically. The default port type is coax port.
for d in ports:
@@ -96,22 +94,16 @@
port_name=port_name
)
-###############################################################################
-# Cutout
-# ~~~~~~
-# Delete all irrelevant nets.
+# ### Cutout
+#
+# Retain only relevant parts of the layout.
nets = []
nets.extend(nets_p)
nets.extend(nets_n)
-
edbapp.cutout(signal_list=nets, reference_list=["GND"], extent_type="Bounding")
-
-###############################################################################
-# Create SYZ analysis setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create SIwave SYZ setup.
+# Set up the model for network analysis in SIwave.
setup = edbapp.create_siwave_syz_setup("setup1")
setup.add_frequency_sweep(frequency_sweep=[
@@ -120,48 +112,45 @@
["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
])
-###############################################################################
-# Save and close AEDT
-# ~~~~~~~~~~~~~~~~~~~
-# Close AEDT.
+# Save and close the EDB.
edbapp.save()
edbapp.close_edb()
-###############################################################################
-# Launch Hfss3dLayout
-# ~~~~~~~~~~~~~~~~~~~
-# To do SYZ analysis, you must launch HFSS 3D Layout and import EDB into it.
+# ### Launch Hfss3dLayout
+#
+# The HFSS 3D Layout user inteface in AEDT is used to import the EDB and
+# run the analysis. AEDT 3D Layout can be used to view the model
+# if it is launched in graphical mode.
-h3d = pyaedt.Hfss3dLayout(targetfile, specified_version="2023.2", new_desktop_session=True)
+h3d = pyaedt.Hfss3dLayout(edb_full_path,
+ specified_version="2023.2",
+ non_graphical=False, # Set to true for non-graphical mode.
+ new_desktop_session=True)
-###############################################################################
-# Set differential pair
-# ~~~~~~~~~~~~~~~~~~~~~
-# Set differential pair.
+# Define the differential pair.
-h3d.set_differential_pair(positive_terminal="U1_PCIe_Gen4_TX3_CAP_P", negative_terminal="U1_PCIe_Gen4_TX3_CAP_N", diff_name="PAIR_U1")
-h3d.set_differential_pair(positive_terminal="X1_PCIe_Gen4_TX3_P", negative_terminal="X1_PCIe_Gen4_TX3_N", diff_name="PAIR_X1")
+h3d.set_differential_pair(positive_terminal="U1_PCIe_Gen4_TX3_CAP_P",
+ negative_terminal="U1_PCIe_Gen4_TX3_CAP_N",
+ diff_name="PAIR_U1")
+h3d.set_differential_pair(positive_terminal="X1_PCIe_Gen4_TX3_P",
+ negative_terminal="X1_PCIe_Gen4_TX3_N",
+ diff_name="PAIR_X1")
-###############################################################################
-# Solve and plot results
-# ~~~~~~~~~~~~~~~~~~~~~~
# Solve and plot the results.
h3d.analyze(num_cores=4)
-###############################################################################
-# Create report outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a report.
+# Visualze the results.
h3d.post.create_report("dB(S(PAIR_U1,PAIR_U1))", context="Differential Pairs")
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
# Close AEDT.
h3d.save_project()
print("Project is saved to {}".format(h3d.project_path))
h3d.release_desktop(True, True)
+
+# The following cell cleans up the temporary directory and removes all project data.
+
+temp_dir.cleanup()
diff --git a/examples/00-EDB/Readme.txt b/examples/00-EDB/Readme.txt
deleted file mode 100644
index c7104afa4d1..00000000000
--- a/examples/00-EDB/Readme.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-EDB examples
-~~~~~~~~~~~~
-These examples use EDB (Electronics Database) with PyAEDT.
-EDB is a powerful API that allows to control PCB data efficently.
-You can either use EDB standalone or embedded in HFSS 3D Layout in AEDT.
diff --git a/doc/source/_static/connector_example.png b/examples/00-EDB/_static/connector_example.png
similarity index 100%
rename from doc/source/_static/connector_example.png
rename to examples/00-EDB/_static/connector_example.png
diff --git a/examples/00-EDB/_static/diff_via.png b/examples/00-EDB/_static/diff_via.png
new file mode 100644
index 00000000000..d444d1ccbe6
Binary files /dev/null and b/examples/00-EDB/_static/diff_via.png differ
diff --git a/doc/source/_static/edb_example_12_sma_connector_on_board.png b/examples/00-EDB/_static/edb_example_12_sma_connector_on_board.png
similarity index 100%
rename from doc/source/_static/edb_example_12_sma_connector_on_board.png
rename to examples/00-EDB/_static/edb_example_12_sma_connector_on_board.png
diff --git a/doc/source/_static/parametrized_design.png b/examples/00-EDB/_static/parameterized_design.png
similarity index 100%
rename from doc/source/_static/parametrized_design.png
rename to examples/00-EDB/_static/parameterized_design.png
diff --git a/examples/00-EDB/_static/pcb_transition_parameterized.png b/examples/00-EDB/_static/pcb_transition_parameterized.png
new file mode 100644
index 00000000000..f75d4a2e673
Binary files /dev/null and b/examples/00-EDB/_static/pcb_transition_parameterized.png differ
diff --git a/examples/00-EDB/index.rst b/examples/00-EDB/index.rst
new file mode 100644
index 00000000000..b989ef9ede4
--- /dev/null
+++ b/examples/00-EDB/index.rst
@@ -0,0 +1,26 @@
+.. _ref_examples_gallery:
+
+EDB examples
+~~~~~~~~~~~~
+
+These examples use EDB (Electronics Database) with PyAEDT.
+EDB is a flexible API that provides efficient control of PCB data.
+The EDB can be used standalone or in combination with the
+electronics desktop user interface.
+
+.. nbgallery::
+
+ 00_EDB_Create_VIA.py
+ 01_edb_example.py
+ 02_edb_to_ipc2581.py
+ 03_5G_antenna_example_parametrics.py
+ 04_edb_parametrized_design.py
+ 05_Plot_nets.py
+ 06_Advanced_EDB.py
+ 09_Configuration.py
+ 10_GDS_workflow.py
+ 11_post_layout_parameterization.py
+ 12_edb_sma_connector_on_board.py
+ 13_edb_create_component.py
+ 14_edb_create_parametrized_design.py
+ 15_ac_analysis.py
diff --git a/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py b/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py
index d780f782671..061218cd7d9 100644
--- a/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py
+++ b/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py
@@ -1,30 +1,24 @@
-"""
-HFSS 3D Layout: SIwave DCIR analysis in HFSS 3D Layout
-------------------------------------------------------
-This example shows how you can use configure HFSS 3D Layout for SIwave DCIR
-analysis.
-"""
+# # HFSS 3D Layout: SIwave DCIR analysis in HFSS 3D Layout
+#
+# This example shows how to configure a model using the 3D Layout
+# interface for SIwave DC-IR analysis.
import os
import tempfile
import pyaedt
-###############################################################################
-# Configure EDB for DCIR analysis
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Copy example into temporary folder
-temp_dir = tempfile.gettempdir()
-dst_dir = os.path.join(temp_dir, pyaedt.generate_unique_name("pyaedt_dcir"))
+
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+dst_dir = os.path.join(temp_dir.name, "pyaedt_dcir")
os.mkdir(dst_dir)
local_path = pyaedt.downloads.download_aedb(dst_dir)
-#####################################################################################
# Load example board into EDB
edbversion = "2023.2"
appedb = pyaedt.Edb(local_path, edbversion=edbversion)
-#####################################################################################
# Create pin group on VRM positive pins
gnd_name = "GND"
@@ -33,7 +27,6 @@
net_name="BST_V3P3_S5",
group_name="U3A1-BST_V3P3_S5")
-#####################################################################################
# Create pin group on VRM negative pins
appedb.siwave.create_pin_group_on_net(
@@ -41,8 +34,8 @@
net_name="GND",
group_name="U3A1-GND")
-#####################################################################################
# Create voltage source between VRM positive and negative pin groups
+
appedb.siwave.create_voltage_source_on_pin_group(
pos_pin_group_name="U3A1-BST_V3P3_S5",
neg_pin_group_name="U3A1-GND",
@@ -50,7 +43,6 @@
name="U3A1-BST_V3P3_S5"
)
-#####################################################################################
# Create pin group on sink component positive pins
appedb.siwave.create_pin_group_on_net(
@@ -58,7 +50,6 @@
net_name="V3P3_S5",
group_name="U2A5-V3P3_S5")
-#####################################################################################
# Create pin group on sink component negative pins
appedb.siwave.create_pin_group_on_net(
@@ -66,8 +57,8 @@
net_name="GND",
group_name="U2A5-GND")
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create place current source between sink component positive and negative pin groups
+# Create place current source between sink component positive and negative pin groups.
+
appedb.siwave.create_current_source_on_pin_group(
pos_pin_group_name="U2A5-V3P3_S5",
neg_pin_group_name="U2A5-GND",
@@ -75,61 +66,50 @@
name="U2A5-V3P3_S5"
)
-###############################################################################
# Add SIwave DCIR analysis
appedb.siwave.add_siwave_dc_analysis(name="my_setup")
-###############################################################################
-# Save and close EDB
-# ~~~~~~~~~~~~~~~~~~
# Save and close EDB.
appedb.save_edb()
appedb.close_edb()
-###############################################################################
-# Analysis DCIR in AEDT
-# ~~~~~~~~~~~~~~~~~~~~~
# Launch AEDT and import the configured EDB and analysis DCIR
+
desktop = pyaedt.Desktop(edbversion, non_graphical=False, new_desktop_session=True)
hfss3dl = pyaedt.Hfss3dLayout(local_path)
hfss3dl.analyze()
hfss3dl.save_project()
-###############################################################################
-# Get element data
-# ~~~~~~~~~~~~~~~~~~~
# Get loop resistance
loop_resistance = hfss3dl.get_dcir_element_data_loop_resistance(setup_name="my_setup")
print(loop_resistance)
-# ~~~~~~~~~~~~~~~~~~~
# Get current source
current_source = hfss3dl.get_dcir_element_data_current_source(setup_name="my_setup")
print(current_source)
-# ~~~~~~~~~~~~~~~~~~~
# Get via information
via = hfss3dl.get_dcir_element_data_via(setup_name="my_setup")
print(via)
+# Get voltage from the DC-IR solution data.
-###############################################################################
-# Get voltage
-# ~~~~~~~~~~~
-# Get voltage from dcir solution data
voltage = hfss3dl.get_dcir_solution_data(
setup_name="my_setup",
show="Sources",
category="Voltage")
print({expression: voltage.data_magnitude(expression) for expression in voltage.expressions})
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+
hfss3dl.close_project()
desktop.release_desktop()
+
+# Clean up the temporary directory.
+
+temp_dir.cleanup()
diff --git a/examples/01-HFSS3DLayout/EDB_in_3DLayout.py b/examples/01-HFSS3DLayout/EDB_in_3DLayout.py
index 48e973b8e9a..9c9c36bda97 100644
--- a/examples/01-HFSS3DLayout/EDB_in_3DLayout.py
+++ b/examples/01-HFSS3DLayout/EDB_in_3DLayout.py
@@ -1,103 +1,76 @@
-"""
-HFSS 3D Layout: PCB and EDB in 3D layout
-----------------------------------------
-This example shows how you can use HFSS 3D Layout combined with EDB to
-interact with a 3D layout.
-"""
-
+# # HFSS 3D Layout: PCB and EDB in 3D layout
+#
+# This example shows how you can use HFSS 3D Layout combined with EDB to
+# interact with a 3D layout.
import os
import tempfile
import pyaedt
-tmpfold = tempfile.gettempdir()
-temp_folder = os.path.join(tmpfold, pyaedt.generate_unique_name("Example"))
-if not os.path.exists(temp_folder):
- os.makedirs(temp_folder)
-print(temp_folder)
+temp_dir = tempfile.TemporaryDirectory(suffx=".ansys")
+project_folder = os.path.join(temp_dir.name, "Example")
+if not os.path.exists(project_folder):
+ os.makedirs(project_folder)
+print(project_folder)
-###############################################################################
-# Copy example into temporary folder
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Copy an example into the temporary folder.
+# Copy an example into the temporary project folder.
targetfile = pyaedt.downloads.download_aedb()
print(targetfile)
aedt_file = targetfile[:-12] + "aedt"
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode.
-# You can set ``non_graphical`` either to ``True`` or ``False``.
+# Set ``non_graphical`` to ``True`` in order to run in non-graphical mode.
+# The example is currently set up to run in graphical mode.
non_graphical = False
NewThread = True
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
-# Launch AEDT 2022R2 in graphical mode using SI units.
+# Launch AEDT 2023R2 in graphical mode. Units are SI.
desktopVersion = "2023.2"
-###############################################################################
-# Initialize AEDT and launch HFSS 3D Layout
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize AEDT and launch HFSS 3D Layout
+#
# Initialize AEDT and launch HFSS 3D Layout.
-# The ``h3d`` object contains the :class:`pyaedt.Edb` class query methods.
+# The ``h3d`` object contains the `pyaedt.Edb` class query methods.
d = pyaedt.launch_desktop(desktopVersion, non_graphical, NewThread)
if os.path.exists(aedt_file):
os.remove(aedt_file)
h3d = pyaedt.Hfss3dLayout(targetfile)
-h3d.save_project(os.path.join(temp_folder, "edb_demo.aedt"))
+h3d.save_project(os.path.join(project_folder, "edb_demo.aedt"))
-###############################################################################
-# Print boundaries
-# ~~~~~~~~~~~~~~~~
+# ## Print boundaries
+#
# Print boundaries from the ``setups`` object.
h3d.boundaries
-###############################################################################
-# Hide all nets
-# ~~~~~~~~~~~~~
# Hide all nets.
h3d.modeler.change_net_visibility(visible=False)
-###############################################################################
-# Show only two nets
-# ~~~~~~~~~~~~~~~~~~
# Show only two specified nets.
h3d.modeler.change_net_visibility(["A0_GPIO", "A0_MUX"], visible=True)
edb = h3d.modeler.edb
edb.nets.plot(["A0_GPIO", "A0_MUX"])
-###############################################################################
-# Show all layers
-# ~~~~~~~~~~~~~~~
# Show all layers.
for layer in h3d.modeler.layers.all_signal_layers:
layer.is_visible = True
-###############################################################################
-# Change layer color
-# ~~~~~~~~~~~~~~~~~~
# Change the layer color.
layer = h3d.modeler.layers.layers[h3d.modeler.layers.layer_id("TOP")]
layer.set_layer_color(0, 255, 0)
h3d.modeler.fit_all()
-###############################################################################
-# Disable component visibility
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Disable component visibility for ``"TOP"`` and ``"BOTTOM"``.
-# The :func:`pyaedt.modules.LayerStackup.Layer.update_stackup_layer` method
+# ## Disable component visibility
+#
+# Disable component visibility for ``"TOP"`` and ``"BOTTOM"`` layers.
+# The `pyaedt.modules.LayerStackup.Layer.update_stackup_layer` method
# applies modifications to the layout.
top = h3d.modeler.layers.layers[h3d.modeler.layers.layer_id("TOP")]
@@ -106,19 +79,21 @@
bot = h3d.modeler.layers.layers[h3d.modeler.layers.layer_id("BOTTOM")]
bot.is_visible_component = False
-###############################################################################
-# Fit all
-# ~~~~~~~
+# ## Display the Layout
+#
# Fit all so that you can visualize all.
h3d.modeler.fit_all()
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
+# `pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
h3d.close_project()
d.release_desktop()
+
+# Clean up the temporary directory and remove all files.
+
+temp_dir.cleanup()
diff --git a/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py b/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py
index e769c1a26b6..c0d8f9e5c52 100644
--- a/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py
+++ b/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py
@@ -1,35 +1,23 @@
-"""
-HFSS 3D Layout: parametric via analysis
----------------------------------------
-This example shows how you can use HFSS 3D Layout to create and solve a
-parametric via analysis.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS 3D Layout: parametric via analysis
+#
+# This example shows how you can use HFSS 3D Layout to create and solve a
+
# Perform required imports.
+
import pyaedt
import os
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = True
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
# Launch AEDT 2023 R2 in graphical mode.
h3d = pyaedt.Hfss3dLayout(specified_version="2023.2", new_desktop_session=True, non_graphical=non_graphical)
-###############################################################################
-# Set up variables
-# ~~~~~~~~~~~~~~~~
# Set up all parametric variables to use in the layout.
h3d["viatotrace"] = "5mm"
@@ -38,27 +26,18 @@
h3d["sp"] = "0.5mm"
h3d["len"] = "50mm"
-###############################################################################
-# Add stackup layers
-# ~~~~~~~~~~~~~~~~~~
# Add stackup layers.
h3d.modeler.layers.add_layer(layername="GND", layertype="signal", thickness="0", isnegative=True)
h3d.modeler.layers.add_layer(layername="diel", layertype="dielectric", thickness="0.2mm", material="FR4_epoxy")
h3d.modeler.layers.add_layer(layername="TOP", layertype="signal", thickness="0.035mm", elevation="0.2mm")
-###############################################################################
-# Create signal net and ground planes
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a signal net and ground planes.
h3d.modeler.create_line(layername="TOP", center_line_list=[[0, 0], ["len", 0]], lw="w1", netname="microstrip", name="microstrip")
h3d.modeler.create_rectangle(layername="TOP", origin=[0, "-w1/2-sp"], dimensions=["len", "-w1/2-sp-20mm"])
h3d.modeler.create_rectangle(layername="TOP", origin=[0, "w1/2+sp"], dimensions=["len", "w1/2+sp+20mm"])
-###############################################################################
-# Create vias
-# ~~~~~~~~~~~
# Create vias with parametric positions.
h3d.modeler.create_via(x="viatovia", y="-viatotrace", name="via1")
@@ -68,17 +47,11 @@
h3d.modeler.create_via(x="3*viatovia", y="-viatotrace")
h3d.modeler.create_via(x="3*viatovia", y="viatotrace")
-###############################################################################
-# Create circuit ports
-# ~~~~~~~~~~~~~~~~~~~~
# Create circuit ports.
h3d.create_edge_port("microstrip", 0)
h3d.create_edge_port("microstrip", 2)
-###############################################################################
-# Create setup and sweep
-# ~~~~~~~~~~~~~~~~~~~~~~
# Create a setup and a sweep.
setup = h3d.create_setup()
@@ -96,30 +69,25 @@
use_q3d_for_dc=False,
)
-###############################################################################
-# Solve and plot results
-# ~~~~~~~~~~~~~~~~~~~~~~
# Solve and plot the results.
h3d.analyze()
traces = h3d.get_traces_for_plot(first_element_filter="Port1")
h3d.post.create_report(traces, variations=h3d.available_variations.nominal_w_values_dict)
-###############################################################################
-# Create report outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a report using Matplotlib.
+# Display the results using [Matplotlib](https://matplotlib.org/stable/users/getting_started/).
+# +
traces = h3d.get_traces_for_plot(first_element_filter="Port1", category="S")
solutions = h3d.post.get_solution_data(expressions=traces)
solutions.plot(math_formula="db20")
+# -
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
+# `pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
h3d.release_desktop()
diff --git a/examples/01-HFSS3DLayout/Hfss3DComponent.py b/examples/01-HFSS3DLayout/Hfss3DComponent.py
index 2fcf13eaa54..0d532c83c9f 100644
--- a/examples/01-HFSS3DLayout/Hfss3DComponent.py
+++ b/examples/01-HFSS3DLayout/Hfss3DComponent.py
@@ -1,22 +1,16 @@
-"""
-HFSS: 3D Components
--------------------
-This example shows how you can use PyAEDT to place 3D Components in Hfss and in Hfss 3D Layout.
-"""
+# # HFSS: 3D Components
+#
+# This example shows how you can use PyAEDT to place 3D Components in Hfss and in Hfss 3D Layout.
+
import os
import pyaedt
+import tempfile
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Common Properties
-# ~~~~~~~~~~~~~~~~~
# Set common properties.
trace_width = 0.6
@@ -28,39 +22,35 @@
desktop_version = "2023.2"
new_session = True
-###############################################################################
-# 3D Component Definition
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# File to be used in the example
+# ## 3D Component Definition
+#
+# Download the 3D component file.
component3d = pyaedt.downloads.download_file("component_3d", "SMA_RF_Jack.a3dcomp",)
-###############################################################################
-# Hfss Example
-# ------------
+# ## Hfss Example
+#
# This example will create a stackup in Hfss place a 3d component, build a ground plane, a trace,
# create excitation and solve it in Hfss.
-
-###############################################################################
-# Launch Hfss
-# ~~~~~~~~~~~
+#
# Launch HFSS application
-hfss = pyaedt.Hfss(new_desktop_session=True, specified_version="2023.2", non_graphical=non_graphical)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+projectname = os.path.join("component_demo.aedt")
+hfss = pyaedt.Hfss(projectname=projectname,
+ new_desktop_session=True,
+ specified_version=desktop_version,
+ non_graphical=non_graphical)
hfss.solution_type = "Terminal"
-###############################################################################
-# Insert 3d Component
-# ~~~~~~~~~~~~~~~~~~~
# To insert a 3d component we need to read parameters and then import in Hfss.
comp_param = hfss.get_components3d_vars(component3d)
hfss.modeler.insert_3d_component(component3d, comp_param)
-###############################################################################
-# Add a new Stackup
-# ~~~~~~~~~~~~~~~~~
+# ## Define the Stackup
+#
# Pyaedt has a Stackup class which allows to parametrize stacked structures.
stackup = hfss.add_stackup_3d()
@@ -68,9 +58,6 @@
d1 = stackup.add_dielectric_layer("D1", thickness=diel_height)
g1 = stackup.add_ground_layer("G1", thickness=sig_height)
-###############################################################################
-# Define stackup extensions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define stackup elevation and size. Defines also the stackup origin.
stackup.start_position = "-131mil"
@@ -79,9 +66,8 @@
stackup.dielectric_y_position = "-dielectric_width/2"
stackup.dielectric_x_position = "-dielectric_length/4"
-###############################################################################
-# Padstack Definition
-# ~~~~~~~~~~~~~~~~~~~
+# ## Padstack Definition
+#
# Padstacks are needed to create a clearance around 3d component since
# intersections are not allowed. There will be 1 padstack for Gnd and 1 for pin.
@@ -104,9 +90,8 @@
p2.padstacks_by_layer["L1"].pad_radius = 0.3048
p2.add_via(0, 0)
-###############################################################################
-# Trace Definition
-# ~~~~~~~~~~~~~~~~
+# ## Trace Definition
+#
# The trace will connect the pin to the port on layer L1.
t1 = s1.add_trace(trace_width, trace_length)
@@ -115,19 +100,17 @@
dimension_list=["15*" + t1.width.name, "-3*" + stackup.thickness.name])
p1 = hfss.wave_port(signal=rect1, reference="G1", name="P1")
-###############################################################################
-# Set Simulation Boundaries
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set Simulation Boundaries
+#
# Define regione and simulation boundaries.
hfss.change_material_override(True)
-region = hfss.modeler.create_region([0, 0, 0, 0, 0, 100])
+region = hfss.modeler.create_region([100, 100, 100, 100, 100, 100])
sheets = [i for i in region.faces]
hfss.assign_radiation_boundary_to_faces(sheets)
-###############################################################################
-# Create Setup
-# ~~~~~~~~~~~~
+# ## Create Setup
+#
# Iterations will be reduced to reduce simulation time.
setup1 = hfss.create_setup()
@@ -135,48 +118,42 @@
setup1.props["Frequency"] = freq
setup1.props["MaximumPasses"] = max_steps
-###############################################################################
-# Solve Setup
-# ~~~~~~~~~~~
+# ## Solve Setup
+#
# Save the project first and then solve the setup.
hfss.save_project()
hfss.analyze()
-###############################################################################
-# Plot results
-# ~~~~~~~~~~~~
+# ## Plot results
+#
# Plot the results when analysis is completed.
traces = hfss.get_traces_for_plot(category="S")
solutions = hfss.post.get_solution_data(traces)
solutions.plot(traces, math_formula="db20")
-###############################################################################
-# Hfss 3D Layout Example
-# ----------------------
+# ## Hfss 3D Layout Example
+#
# Previous example will be repeated this time in Hfss 3d Layout.
# Small differences are expected in layout but results should be similar.
-###############################################################################
-# Launch Hfss3dLayout
-# ~~~~~~~~~~~~~~~~~~~
+# ## Launch Hfss3dLayout
+#
# Launch HFSS3dLayout application
h3d = pyaedt.Hfss3dLayout()
-###############################################################################
-# Add stackup layers
-# ~~~~~~~~~~~~~~~~~~
+# ## Add stackup layers
+#
# Add stackup layers.
l1 = h3d.modeler.layers.add_layer("L1", "signal", thickness=sig_height)
h3d.modeler.layers.add_layer("diel", "dielectric", thickness=diel_height, material="FR4_epoxy")
h3d.modeler.layers.add_layer("G1", "signal", thickness=sig_height, isnegative=True)
-###############################################################################
-# Place 3d Component
-# ~~~~~~~~~~~~~~~~~~
+# ## Place 3d Component
+#
# Place a 3d component by specifying the .a3dcomp file path.
comp = h3d.modeler.place_3d_component(
@@ -184,9 +161,8 @@
pos_x=0.000, pos_y=0.000
)
-###############################################################################
-# Create signal net and ground planes
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create signal net and ground planes
+#
# Create a signal net and ground planes.
h3d["len"] = str(trace_length) + "mm"
@@ -194,16 +170,12 @@
line = h3d.modeler.create_line("L1", [[0, 0], ["len", 0]], lw="w1", netname="microstrip", name="microstrip")
h3d.create_edge_port(line, h3d.modeler[line].top_edge_x, iswave=True, wave_horizontal_extension=15, )
-###############################################################################
# Create void on Ground plane for pin
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a void.
h3d.modeler.create_circle("G1", 0, 0, 0.5)
-###############################################################################
-# Create Setup
-# ~~~~~~~~~~~~
+# ## Create Setup
+#
# Iterations will be reduced to reduce simulation time.
h3d.set_meshing_settings(mesh_method="PhiPlus", enable_intersections_check=False)
@@ -214,15 +186,11 @@
setup1.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["AdaptiveFrequency"] = freq
setup1.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["MaxPasses"] = max_steps
-###############################################################################
# Solve Setup
-# ~~~~~~~~~~~
h3d.analyze()
-###############################################################################
# Plot results
-# ~~~~~~~~~~~~
traces = h3d.get_traces_for_plot(category="S")
solutions = h3d.post.get_solution_data(traces)
@@ -230,3 +198,5 @@
h3d.save_project()
h3d.release_desktop()
+
+temp_dir.cleanup() # Remove project folder and files.
diff --git a/examples/01-HFSS3DLayout/Readme.txt b/examples/01-HFSS3DLayout/index.rst
similarity index 63%
rename from examples/01-HFSS3DLayout/Readme.txt
rename to examples/01-HFSS3DLayout/index.rst
index daf9b1637e8..6e8a78a1346 100644
--- a/examples/01-HFSS3DLayout/Readme.txt
+++ b/examples/01-HFSS3DLayout/index.rst
@@ -2,3 +2,10 @@ HFSS 3D Layout examples
~~~~~~~~~~~~~~~~~~~~~~~
These examples use PyAEDT to show some end-to-end workflows for HFSS 3D Layout.
It includes model generation, setup, meshing, and post-processing.
+
+.. nbgallery::
+
+ Dcir_in_3DLayout.py
+ EDB_in_3DLayout.py
+ Hfss3DComponent.py
+ HFSS3DLayout_Via.py
diff --git a/examples/01-Modeling-Setup/Configurations.py b/examples/01-Modeling-Setup/Configurations.py
index 473b1ec9f16..7f8ef5b9b23 100644
--- a/examples/01-Modeling-Setup/Configurations.py
+++ b/examples/01-Modeling-Setup/Configurations.py
@@ -1,77 +1,68 @@
-"""
-General: configuration files
-----------------------------
-This example shows how you can use PyAEDT to export configuration files and re-use
-them to import in a new project. A configuration file is supported by these applications:
-
-* HFSS
-* 2D Extractor and Q3D Extractor
-* Maxwell
-* Icepak (in AEDT)
-* Mechanical (in AEDT)
-
-The following sections are covered:
-
-* Variables
-* Mesh operations (except Icepak)
-* Setup and optimetrics
-* Material properties
-* Object properties
-* Boundaries and excitations
-
-When a boundary is attached to a face, the tool tries to match it with a
-``FaceByPosition`` on the same object name on the target design. If, for
-any reason, this face position has changed or the object name in the target
-design has changed, the boundary fails to apply.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports from PyAEDT.
+# # General: configuration files
+#
+# This example shows how you can use PyAEDT to export configuration files and re-use
+# them to import in a new project. A configuration file is supported by these applications:
+#
+# * HFSS
+# * 2D Extractor and Q3D Extractor
+# * Maxwell
+# * Icepak (in AEDT)
+# * Mechanical (in AEDT)
+#
+# The following sections are covered:
+#
+# * Variables
+# * Mesh operations (except Icepak)
+# * Setup and optimetrics
+# * Material properties
+# * Object properties
+# * Boundaries and excitations
+#
+# When a boundary is attached to a face, the tool tries to match it with a
+# ``FaceByPosition`` on the same object name on the target design. If, for
+# any reason, this face position has changed or the object name in the target
+# design has changed, the boundary fails to apply.
+
+# ## Perform required imports
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode.
+# ## Set non-graphical mode
+
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Open project
-# ~~~~~~~~~~~~
+# ## Open project
+
# Download the project, open it, and save it to the temporary folder.
+# +
project_full_name = pyaedt.downloads.download_icepak(pyaedt.generate_unique_folder_name(folder_name="Graphic_Card"))
ipk = pyaedt.Icepak(projectname=project_full_name, specified_version="2023.2",
new_desktop_session=True, non_graphical=non_graphical)
ipk.autosave_disable()
+# -
-###############################################################################
-# Create source blocks
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Create source blocks
+#
# Create a source block on the CPU and memories.
ipk.create_source_block(object_name="CPU", input_power="25W")
ipk.create_source_block(object_name=["MEMORY1", "MEMORY1_1"], input_power="5W")
-###############################################################################
-# Assign boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Assign boundaries
+#
# Assign the opening and grille.
region = ipk.modeler["Region"]
ipk.assign_openings(air_faces=region.bottom_face_x.id)
ipk.assign_grille(air_faces=region.top_face_x.id, free_area_ratio=0.8)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create the setup. Properties can be set up from the ``setup`` object
# with getters and setters. They don't have to perfectly match the property
# syntax.
@@ -83,9 +74,8 @@
setup1["Solver Type Temperature"] = "flex"
ipk.save_project(r"C:\temp\Graphic_card.aedt")
-###############################################################################
-# Export project to step file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export project to step file
+#
# Export the current project to the step file.
filename = ipk.design_name
@@ -93,36 +83,31 @@
ipk.export_3d_model(file_name=filename, file_path=ipk.working_directory, file_format=".step", object_list=[],
removed_objects=[])
-###############################################################################
-# Export configuration files
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export configuration files
+#
# Export the configuration files. You can optionally disable the export and
# import sections. Supported formats are json and toml files
conf_file = ipk.configurations.export_config(os.path.join(ipk.working_directory, "config.toml"))
ipk.close_project()
-
-###############################################################################
-# Create project
-# ~~~~~~~~~~~~~~
+# ## Create project
+#
# Create an Icepak project and import the step.
app = pyaedt.Icepak(projectname="new_proj_Ipk")
app.modeler.import_3d_cad(file_path)
-###############################################################################
-# Import and apply configuration file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import and apply configuration file
+#
# Import and apply the configuration file. You can apply all or part of the
# JSON file that you import using options in the ``configurations`` object.
out = app.configurations.import_config(conf_file)
app.configurations.results.global_import_success
-###############################################################################
-# Close project
-# ~~~~~~~~~~~~~
+# ## Close project
+#
# Close the project.
app.release_desktop()
diff --git a/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py b/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py
index 29bb7e6abaf..072c633b9df 100644
--- a/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py
+++ b/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py
@@ -1,51 +1,42 @@
-"""
-General: coordinate system creation
------------------------------------
-This example shows how you can use PyAEDT to create and modify coordinate systems in the modeler.
-"""
-###############################################################################
+# # General: coordinate system creation
+#
+# This example shows how you can use PyAEDT to create and modify coordinate systems in the modeler.
+#
+# ## Perform required imports
+#
# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports
-
-import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT in graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT in graphical mode
+#
# Launch AEDT 2023 R2 in graphical mode.
d = pyaedt.launch_desktop(specified_version="2023.2", non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Insert HFSS design
-# ~~~~~~~~~~~~~~~~~~
+# ## Insert HFSS design
+#
# Insert an HFSS design with the default name.
hfss = pyaedt.Hfss(projectname=pyaedt.generate_unique_project_name(folder_name="CoordSysDemo"))
-###############################################################################
-# Create coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system
+#
# The coordinate system is centered on the global origin and has the axis
# aligned to the global coordinate system. The new coordinate system is
# saved in the object ``cs1``.
cs1 = hfss.modeler.create_coordinate_system()
-###############################################################################
-# Modify coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Modify coordinate system
+#
# The ``cs1`` object exposes properties and methods to manipulate the
# coordinate system. The origin can be changed.
@@ -60,16 +51,14 @@
cs1.props["YAxisYvec"] = ypoint[1]
cs1.props["YAxisZvec"] = ypoint[2]
-###############################################################################
-# Rename coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Rename coordinate system
+#
# Rename the coordinate system.
cs1.rename("newCS")
-###############################################################################
-# Change coordinate system mode
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Change coordinate system mode
+#
# Use the ``change_cs_mode`` method to change the mode. Options are ``0``
# for axis/position, ``1`` for Euler angle ZXZ, and ``2`` for Euler angle ZYZ.
# Here ``1`` sets Euler angle ZXZ as the mode.
@@ -77,20 +66,19 @@
cs1.change_cs_mode(1)
# In the new mode, these properties can be edited
+
cs1.props["Phi"] = "10deg"
cs1.props["Theta"] = "22deg"
cs1.props["Psi"] = "30deg"
-###############################################################################
-# Delete coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Delete coordinate system
+#
# Delete the coordinate system.
cs1.delete()
-###############################################################################
-# Create coordinate system by defining axes
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system by defining axes
+#
# Create a coordinate system by defining the axes. During creation, you can
# specify all coordinate system properties.
@@ -98,34 +86,30 @@
name="CS2", origin=[1, 2, 3.5], mode="axis", x_pointing=[1, 0, 1], y_pointing=[0, -1, 0]
)
-###############################################################################
-# Create coordinate system by defining Euler angles
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system by defining Euler angles
+#
# Create a coordinate system by defining Euler angles.
cs3 = hfss.modeler.create_coordinate_system(name="CS3", origin=[2, 2, 2], mode="zyz", phi=10, theta=20, psi=30)
-###############################################################################
-# Create coordinate system by defining view
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system by defining view
+#
# Create a coordinate system by defining the view. Options are ``"iso"``,
# ``"XY"``, ``"XZ"``, and ``"XY"``. Here ``"iso"`` is specified.
# The axes are set automatically.
cs4 = hfss.modeler.create_coordinate_system(name="CS4", origin=[1, 0, 0], reference_cs="CS3", mode="view", view="iso")
-###############################################################################
-# Create coordinate system by defining axis and angle rotation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system by defining axis and angle rotation
+#
# Create a coordinate system by defining the axis and angle rotation. When you
# specify the axis and angle rotation, this data is automatically translated
# to Euler angles.
cs5 = hfss.modeler.create_coordinate_system(name="CS5", mode="axisrotation", u=[1, 0, 0], theta=123)
-###############################################################################
-# Create face coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create face coordinate system
+#
# Face coordinate systems are bound to an object face.
# First create a box and then define the face coordinate system on one of its
# faces. To create the reference face for the face coordinate system, you must
@@ -137,9 +121,8 @@
face=face, origin=face.edges[0], axis_position=face.edges[1], name="FCS1"
)
-###############################################################################
-# Create face coordinate system centered on face
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create face coordinate system centered on face
+#
# Create a face coordinate system centered on the face with the X axis pointing
# to the edge vertex.
@@ -147,9 +130,8 @@
face=face, origin=face, axis_position=face.edges[0].vertices[0], name="FCS2"
)
-###############################################################################
-# Swap X and Y axes of face coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Swap X and Y axes of face coordinate system
+#
# Swap the X axis and Y axis of the face coordinate system. The X axis is the
# pointing ``axis_position`` by default. You can optionally select the Y axis.
@@ -158,9 +140,9 @@
# Axis can also be changed after coordinate system creation
fcs3.props["WhichAxis"] = "X"
-###############################################################################
-# Apply a rotation around Z axis
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Apply a rotation around Z axis
+#
# Apply a rotation around the Z axis. The Z axis of a face coordinate system
# is always orthogonal to the face. A rotation can be applied at definition.
# Rotation is expressed in degrees.
@@ -170,9 +152,8 @@
# Rotation can also be changed after coordinate system creation
fcs4.props["ZRotationAngle"] = "3deg"
-###############################################################################
-# Apply offset to X and Y axes of face coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Apply offset to X and Y axes of face coordinate system
+#
# Apply an offset to the X axis and Y axis of a face coordinate system.
# The offset is in respect to the face coordinate system itself.
@@ -184,9 +165,8 @@
fcs5.props["XOffset"] = "0.2mm"
fcs5.props["YOffset"] = "0.1mm"
-###############################################################################
-# Create coordinate system relative to face coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system relative to face coordinate system
+#
# Create a coordinate system relative to a face coordinate system. Coordinate
# systems and face coordinate systems interact with each other.
@@ -196,9 +176,8 @@
name="CS_FCS", origin=[0, 0, 0], reference_cs=fcs6.name, mode="view", view="iso"
)
-###############################################################################
-# Create object coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object coordinate system
+#
# Create object coordinate system with origin on face
obj_cs = hfss.modeler.create_object_coordinate_system(
@@ -206,9 +185,8 @@
)
obj_cs.rename("new_obj_cs")
-###############################################################################
-# Create object coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object coordinate system
+#
# Create object coordinate system with origin on edge
obj_cs_1 = hfss.modeler.create_object_coordinate_system(
@@ -216,9 +194,8 @@
)
obj_cs_1.set_as_working_cs()
-###############################################################################
-# Create object coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object coordinate system
+#
# Create object coordinate system with origin specified on point
obj_cs_2 = hfss.modeler.create_object_coordinate_system(
@@ -227,9 +204,8 @@
new_obj_cs_2 = hfss.modeler.duplicate_coordinate_system_to_global(obj_cs_2)
obj_cs_2.delete()
-###############################################################################
-# Create object coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object coordinate system
+#
# Create object coordinate system with origin on vertex
obj_cs_3 = hfss.modeler.create_object_coordinate_system(
@@ -238,27 +214,24 @@
obj_cs_3.props["MoveToEnd"] = False
obj_cs_3.update()
-###############################################################################
-# Get all coordinate systems
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# Get ## all coordinate systems
+#
# Get all coordinate systems.
css = hfss.modeler.coordinate_systems
names = [i.name for i in css]
print(names)
-###############################################################################
-# Select coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Select coordinate system
+#
# Select an existing coordinate system.
css = hfss.modeler.coordinate_systems
cs_selected = css[0]
cs_selected.delete()
-###############################################################################
-# Get point coordinate under another coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get point coordinate under another coordinate system
+#
# Get a point coordinate under another coordinate system. A point coordinate
# can be translated in respect to any coordinate system.
@@ -268,11 +241,10 @@
p2 = hfss.modeler.global_to_cs(p, "CS5")
print("CS5 :", p2)
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulaton completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
+# `pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
d.release_desktop()
diff --git a/examples/01-Modeling-Setup/Optimetrics.py b/examples/01-Modeling-Setup/Optimetrics.py
index 6d30d4c5d74..e87b46ca409 100644
--- a/examples/01-Modeling-Setup/Optimetrics.py
+++ b/examples/01-Modeling-Setup/Optimetrics.py
@@ -1,29 +1,25 @@
-"""
-General: optimetrics setup
---------------------------
-This example shows how you can use PyAEDT to create a project in HFSS and create all optimetrics setups.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # General: optimetrics setup
+#
+# This example shows how you can use PyAEDT to create a project in HFSS and create all optimetrics setups.
+
+
+# ## Perform required imports
+#
# Perform required imports.
import pyaedt
import os
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Initialize object and create variables
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize object and create variables
+#
# Initialize the ``Hfss`` object and create two needed design variables,
# ``w1`` and ``w2``.
@@ -31,12 +27,12 @@
hfss["w1"] = "1mm"
hfss["w2"] = "100mm"
-###############################################################################
-# Create waveguide with sheets on it
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create waveguide with sheets on it
+#
# Create one of the standard waveguide structures and parametrize it.
# You can also create rectangles of waveguide openings and assign ports later.
+# +
wg1, p1, p2 = hfss.modeler.create_waveguide(
[0, 0, 0],
hfss.AXIS.Y,
@@ -50,18 +46,15 @@
model.show_grid = False
model.plot(os.path.join(hfss.working_directory, "Image.jpg"))
+# -
-###############################################################################
-# Create wave ports on sheets
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create two wave ports on the sheets.
hfss.wave_port(p1, integration_line=hfss.AxisDir.ZPos, name="1")
hfss.wave_port(p2, integration_line=hfss.AxisDir.ZPos, name="2")
-###############################################################################
-# Create setup and frequency sweep
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and frequency sweep
+#
# Create a setup and a frequency sweep to use as the base for optimetrics
# setups.
@@ -70,11 +63,10 @@
setupname=setup.name, unit="GHz", freqstart=1, freqstop=5, step_size=0.1, sweepname="Sweep1", save_fields=True
)
-###############################################################################
-# Optimetrics analysis
-# ----------------------
-# Create parametrics analysis
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Optimetrics analysis
+#
+# ### Parametric Analysis
+#
# Create a simple optimetrics parametrics analysis with output calculations.
sweep = hfss.parametrics.add("w2", 90, 200, 5)
@@ -82,18 +74,12 @@
sweep.add_calculation(calculation="dB(S(1,1))", ranges={"Freq": "2.5GHz"})
sweep.add_calculation(calculation="dB(S(1,1))", ranges={"Freq": "2.6GHz"})
-###############################################################################
-# Create sensitivity analysis
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an optimetrics sensitivity analysis with output calculations.
sweep2 = hfss.optimizations.add(calculation="dB(S(1,1))", ranges={"Freq": "2.5GHz"}, optim_type="Sensitivity")
sweep2.add_variation("w1", 0.1, 3, 0.5)
sweep2.add_calculation(calculation="dB(S(1,1))", ranges={"Freq": "2.6GHz"})
-###############################################################################
-# Create optimization based on goals and calculations
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an optimization analysis based on goals and calculations.
sweep3 = hfss.optimizations.add(calculation="dB(S(1,1))", ranges={"Freq": "2.5GHz"})
@@ -106,25 +92,18 @@
condition="Maximize",
)
-###############################################################################
-# Create DX optimization based on a goal and calculation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a DX (DesignXplorer) optimization based on a goal and a calculation.
sweep4 = hfss.optimizations.add(calculation="dB(S(1,1))", ranges={"Freq": "2.5GHz"}, optim_type="DesignExplorer")
sweep4.add_goal(calculation="dB(S(1,1))", ranges={"Freq": "2.6GHz"})
-###############################################################################
-# Create DOE based on a goal and calculation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create DOE based on a goal and calculation
+#
# Create a DOE (Design of Experiments) based on a goal and a calculation.
sweep5 = hfss.optimizations.add(calculation="dB(S(1,1))", ranges={"Freq": "2.5GHz"}, optim_type="DXDOE")
-###############################################################################
-# Create DOE based on a goal and calculation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a DOE based on a goal and a calculation.
+# ## Create DOE based on a goal and calculation
region = hfss.modeler.create_region()
hfss.assign_radiation_boundary_to_objects(region)
@@ -136,9 +115,8 @@
context="Infinite_1",
)
-###############################################################################
-# Close AEDT
-# ----------
+# ## Close AEDT
+#
# After the simulaton completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
diff --git a/examples/01-Modeling-Setup/Polyline_Primitives.py b/examples/01-Modeling-Setup/Polyline_Primitives.py
index c3c3a35c984..3894be107c3 100644
--- a/examples/01-Modeling-Setup/Polyline_Primitives.py
+++ b/examples/01-Modeling-Setup/Polyline_Primitives.py
@@ -1,27 +1,24 @@
-"""
-General: polyline creation
---------------------------
-This example shows how you can use PyAEDT to create and manipulate polylines.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # General: polyline creation
+#
+# This example shows how you can use PyAEDT to create and manipulate polylines.
+
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Create Maxwell 3D object
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Create Maxwell 3D object
+#
# Create a :class:`pyaedt.maxwell.Maxwell3d` object and set the unit type to ``"mm"``.
M3D = pyaedt.Maxwell3d(solution_type="Transient", designname="test_polyline_3D", specified_version="2023.2",
@@ -29,30 +26,27 @@
M3D.modeler.model_units = "mm"
prim3D = M3D.modeler
-###############################################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define two design variables as parameters for the polyline objects.
M3D["p1"] = "100mm"
M3D["p2"] = "71mm"
-###############################################################################
-# Input data
-# ~~~~~~~~~~
+# ## Input data
+#
# Input data. All data for the polyline functions can be entered as either floating point
# values or strings. Floating point values are assumed to be in model units
# (``M3D.modeler.model_units``).
test_points = [["0mm", "p1", "0mm"], ["-p1", "0mm", "0mm"], ["-p1/2", "-p1/2", "0mm"], ["0mm", "0mm", "0mm"]]
-###############################################################################
-# Polyline primitives
-# -------------------
+# ## Polyline primitives
+#
# The following examples are for creating polyline primitives.
-# Create line primitive
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create line primitive
+#
# Create a line primitive. The basic polyline command takes a list of positions
# (``[X, Y, Z]`` coordinates) and creates a polyline object with one or more
# segments. The supported segment types are ``Line``, ``Arc`` (3 points),
@@ -64,9 +58,8 @@
print("Segment types : {}".format([s.type for s in P.segment_types]))
print("primitive id = {}".format(P.id))
-###############################################################################
-# Create arc primitive
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create arc primitive
+#
# Create an arc primitive. The parameter ``position_list`` must contain at
# least three position values. The first three position values are used.
@@ -74,9 +67,8 @@
print("Created object with id {} and name {}.".format(P.id, prim3D.objects[P.id].name))
-###############################################################################
-# Create spline primitive
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create spline primitive
+#
# Create a spline primitive. Defining the segment using a ``PolylineSegment``
# object allows you to provide additional input parameters for the spine, such
# as the number of points (in this case 4). The parameter ``position_list``
@@ -86,9 +78,8 @@
position_list=test_points, segment_type=prim3D.polyline_segment("Spline", num_points=4), name="PL03_spline_4pt"
)
-###############################################################################
-# Create center-point arc primitive
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create center-point arc primitive
+#
# Create a center-point arc primitive. A center-point arc segment is defined
# by a starting point, a center point, and an angle of rotation around the
# center point. The rotation occurs in a plane parallel to the XY, YZ, or ZX
@@ -106,7 +97,6 @@
name="PL04_center_point_arc",
)
-###############################################################################
# Here ``start_point`` and ``center_point`` have the same values for the Y and
# Z coordinates, so the plane or rotation could be either XY or ZX.
# For these special cases when the rotation plane is ambiguous, you can specify
@@ -125,9 +115,8 @@
name="PL04_center_point_arc_rot_ZX",
)
-###############################################################################
-# Compound polylines
-# ------------------
+# ## Compound polylines
+#
# You can use a list of points in a single command to create a multi-segment
# polyline.
#
@@ -136,34 +125,30 @@
P = prim3D.create_polyline(position_list=test_points, name="PL06_segmented_compound_line")
-###############################################################################
# You can specify the segment type with the parameter ``segment_type``.
# In this case, you must specify that the four input points in ``position_list``
# are to be connected as a line segment followed by a 3-point arc segment.
P = prim3D.create_polyline(position_list=test_points, segment_type=["Line", "Arc"], name="PL05_compound_line_arc")
-###############################################################################
# The parameter ``close_surface`` ensures that the polyline starting point and
# ending point are the same. If necessary, you can add an additional line
# segment to achieve this.
P = prim3D.create_polyline(position_list=test_points, close_surface=True, name="PL07_segmented_compound_line_closed")
-###############################################################################
# The parameter ``cover_surface=True`` also performs the modeler command
# ``cover_surface``. Note that specifying ``cover_surface=True`` automatically
# results in the polyline being closed.
P = prim3D.create_polyline(position_list=test_points, cover_surface=True, name="SPL01_segmented_compound_line")
-###############################################################################
-# Compound lines
-# --------------
+# ## Compound lines
+#
# The following examples are for inserting compound lines.
#
-# Insert line segment
-# ~~~~~~~~~~~~~~~~~~~
+# ### Insert line segment
+#
# Insert a line segment starting at vertex 1 ``["100mm", "0mm", "0mm"]``
# of an existing polyline and ending at some new point ``["90mm", "20mm", "0mm"].``
# By numerical comparison of the starting point with the existing vertices of the
@@ -177,9 +162,8 @@
P.insert_segment(position_list=[insert_point, p2])
-###############################################################################
-# Insert compound line with insert curve
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Insert compound line with insert curve
+#
# Insert a compound line starting a line segment at vertex 1 ``["100mm", "0mm", "0mm"]``
# of an existing polyline and end at some new point ``["90mm", "20mm", "0mm"]``.
# By numerical comparison of the starting point, it is determined automatically
@@ -193,9 +177,8 @@
P.insert_segment(position_list=[start_point, insert_point1, insert_point2], segment="Arc")
-###############################################################################
-# Insert compound line at end of a center-point arc
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert compound line at end of a center-point arc
+#
# Insert a compound line at the end of a center-point arc (``type="AngularArc"``).
# This is a special case.
#
@@ -211,7 +194,6 @@
segment_type=prim3D.polyline_segment(type="AngularArc", arc_angle=arc_angle_1, arc_center=arc_center_1),
)
-###############################################################################
# Step 2: Insert a line segment at the end of the arc with a specified end point.
start_of_line_segment = P.end_point
@@ -219,7 +201,6 @@
P.insert_segment(position_list=[start_of_line_segment, end_of_line_segment])
-###############################################################################
# Step 3: Append a center-point arc segment to the line object.
arc_angle_2 = "39.716deg"
@@ -230,7 +211,6 @@
segment=prim3D.polyline_segment(type="AngularArc", arc_center=arc_center_2, arc_angle=arc_angle_2),
)
-###############################################################################
# You can use the compound polyline definition to complete all three steps in
# a single step.
@@ -244,9 +224,8 @@
name="Compound_Polyline_One_Command",
)
-#########################################################################
-# Insert two 3-point arcs forming a circle and covered
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert two 3-point arcs forming a circle and covered
+#
# Insert two 3-point arcs forming a circle and covered.
# Note that the last point of the second arc segment is not defined in
# the position list.
@@ -260,7 +239,6 @@
matname="vacuum",
)
-###############################################################################
# Here is an example of a complex polyline where the number of points is
# insufficient to populate the requested segments. This results in an
# ``IndexError`` that PyAEDT catches silently. The return value of the command
@@ -283,7 +261,6 @@
return_value = prim3D.create_polyline(MDL_points, segment_type=MDL_segments, name="MDL_Polyline")
assert return_value # triggers an error at the application error
-###############################################################################
# Here is an example that provides more points than the segment list requires.
# This is valid usage. The remaining points are ignored.
@@ -291,9 +268,8 @@
P = prim3D.create_polyline(MDL_points, segment_type=MDL_segments, name="MDL_Polyline")
-###############################################################################
-# Save project
-# ------------
+# ## Save project
+#
# Save the project.
project_dir = r"C:\temp"
diff --git a/examples/01-Modeling-Setup/Readme.txt b/examples/01-Modeling-Setup/index.rst
similarity index 58%
rename from examples/01-Modeling-Setup/Readme.txt
rename to examples/01-Modeling-Setup/index.rst
index d9417436357..1cecf178867 100644
--- a/examples/01-Modeling-Setup/Readme.txt
+++ b/examples/01-Modeling-Setup/index.rst
@@ -2,3 +2,10 @@ General model and setup examples
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These examples use PyAEDT to show some general model and simulation
setup features inside AEDT.
+
+.. nbgallery::
+
+ Configurations.py
+ HFSS_CoordinateSystem.py
+ Optimetrics.py
+ Polyline_Primitives.py
diff --git a/examples/02-HFSS/Advanced_Far_Field.py.back b/examples/02-HFSS/Advanced_Far_Field.py.back
deleted file mode 100644
index ab372e63618..00000000000
--- a/examples/02-HFSS/Advanced_Far_Field.py.back
+++ /dev/null
@@ -1,218 +0,0 @@
-"""
-HFSS: advanced far field postprocessing
----------------------------------------
-This example shows how you can use advanced postprocessing functions to create plots
-using Matplotlib without opening the HFSS user interface.
-This examples runs only on Windows using CPython.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
-
-import os
-import time
-
-import pyaedt
-from pyaedt.generic.general_methods import remove_project_lock
-
-project_name = pyaedt.downloads.download_antenna_array()
-
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Set non-graphical mode.
-# You can set ``non_graphical`` either to ``True`` or ``False``.
-
-non_graphical = False
-
-###############################################################################
-# Import modules for postprocessing
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Import modules for postprocessing.
-
-import numpy as np
-import matplotlib.pyplot as plt
-
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
-# Launch AEDT 2023 R1 in non-graphical mode.
-
-desktopVersion = "2023.1"
-NewThread = True
-desktop = pyaedt.launch_desktop(specified_version=desktopVersion,
- non_graphical=non_graphical,
- new_desktop_session=NewThread
- )
-
-###############################################################################
-# Open HFSS project
-# ~~~~~~~~~~~~~~~~~
-# Open the HFSS project. ``Hfss`` class allows to initialize a new project or
-# open an existing project and point to a design name.
-
-remove_project_lock(project_name)
-
-hfss = pyaedt.Hfss(projectname=project_name,
- designname="4X4_MultiCell_CA-Array")
-
-###############################################################################
-# Solve HFSS project
-# ~~~~~~~~~~~~~~~~~~
-# Solves the HFSS project.
-# The solution time is computed.
-
-hfss.analyze_setup("Setup1")
-hfss.save_project()
-
-#######################################
-# Get efields data from solution
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Gets efields data from the solution.
-
-start = time.time()
-ff_data = hfss.post.get_efields_data(ff_setup="3D")
-end = time.time() - start
-print("Postprocessing Time", end)
-
-
-###############################################################################
-# Calculate far field values
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Use Matplotlib to read the solution generated in ``ff_data``. Process
-# the field based on Phi and Theta and generate a plot.
-
-def ff_calc(x=0, y=0, qty="rETotal", dB=True):
- array_size = [4, 4]
- loc_offset = 2 # if array index is not starting at [1,1]
- xphase = float(y)
- yphase = float(x)
- array_shape = (array_size[0], array_size[1])
- weight = np.zeros(array_shape, dtype=complex)
- mag = np.ones(array_shape, dtype="object")
- port_names_arranged = np.chararray(array_shape)
- all_ports = ff_data.keys()
- w_dict = {}
- # calculate weights based off of progressive phase shift
- for m in range(array_shape[0]):
- for n in range(array_shape[1]):
- mag_val = mag[m][n]
- ang = np.radians(xphase * m) + np.radians(yphase * n)
- weight[m][n] = np.sqrt(mag_val) * np.exp(1j * ang)
- current_index_str = "[" + str(m + 1 + loc_offset) + "," + str(n + 1 + loc_offset) + "]"
- port_name = [y for y in all_ports if current_index_str in y]
- w_dict[port_name[0]] = weight[m][n]
-
- length_of_ff_data = len(ff_data[port_name[0]][2])
-
- array_shape = (len(w_dict), length_of_ff_data)
- rEtheta_fields = np.zeros(array_shape, dtype=complex)
- rEphi_fields = np.zeros(array_shape, dtype=complex)
- w = np.zeros((1, array_shape[0]), dtype=complex)
- # create port mapping
- for n, port in enumerate(ff_data.keys()):
- re_theta = ff_data[port][2]
- re_phi = ff_data[port][3]
- re_theta = re_theta * w_dict[port]
-
- w[0][n] = w_dict[port]
- re_phi = re_phi * w_dict[port]
-
- rEtheta_fields[n] = re_theta
- rEphi_fields[n] = re_phi
-
- theta_range = ff_data[port][0]
- phi_range = ff_data[port][1]
- theta = [int(np.min(theta_range)), int(np.max(theta_range)), np.size(theta_range)]
- phi = [int(np.min(phi_range)), int(np.max(phi_range)), np.size(phi_range)]
- Ntheta = len(theta_range)
- Nphi = len(phi_range)
-
- rEtheta_fields = np.dot(w, rEtheta_fields)
- rEtheta_fields = np.reshape(rEtheta_fields, (Ntheta, Nphi))
-
- rEphi_fields = np.dot(w, rEphi_fields)
- rEphi_fields = np.reshape(rEphi_fields, (Ntheta, Nphi))
-
- all_qtys = {}
- all_qtys["rEPhi"] = rEphi_fields
- all_qtys["rETheta"] = rEtheta_fields
- all_qtys["rETotal"] = np.sqrt(np.power(np.abs(rEphi_fields), 2) + np.power(np.abs(rEtheta_fields), 2))
-
- pin = np.sum(w)
- print(str(pin))
- real_gain = 2 * np.pi * np.abs(np.power(all_qtys["rETotal"], 2)) / pin / 377
- all_qtys["RealizedGain"] = real_gain
-
- if dB:
- if "Gain" in qty:
- qty_to_plot = 10 * np.log10(np.abs(all_qtys[qty]))
- else:
- qty_to_plot = 20 * np.log10(np.abs(all_qtys[qty]))
- qty_str = qty + " (dB)"
- else:
- qty_to_plot = np.abs(all_qtys[qty])
- qty_str = qty + " (mag)"
-
- plt.figure(figsize=(25, 15))
- plt.title(qty_str)
- plt.xlabel("Theta (degree)")
- plt.ylabel("Phi (degree)")
-
- plt.imshow(qty_to_plot, cmap="jet")
- plt.colorbar()
-
- np.max(qty_to_plot)
-
-
-###############################################################################
-# Create plot and interact with it
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create the plot and interact with it.
-
-ff_calc()
-
-# interact(ff_calc, x=widgets.FloatSlider(value=0, min=-180, max=180, step=1),
-# y=widgets.FloatSlider(value=0, min=-180, max=180, step=1))
-
-
-vals = hfss.post.get_far_field_data(setup_sweep_name=hfss.nominal_sweep,
- expression="RealizedGainTotal",
- domain="Elevation"
- )
-
-###############################################################################
-# Generate polar plot
-# ~~~~~~~~~~~~~~~~~~~
-# Generate a polar plot.
-
-vals.plot(math_formula="db20", is_polar=True)
-
-###############################################################################
-# Generate scalar plot
-# ~~~~~~~~~~~~~~~~~~~~
-# Generate a scalar plot.
-
-vals.plot(math_formula="db20", is_polar=False)
-
-###############################################################################
-# Generate plot using Phi as primary sweep
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Generate the plot using Phi as the primary sweep.
-
-vals3d = hfss.post.get_far_field_data(setup_sweep_name=hfss.nominal_sweep,
- expression="RealizedGainTotal",
- domain="Infinite Sphere1"
- )
-
-vals3d.plot_3d()
-
-#######################################
-# Close HFSS project and AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Close the HFSS project and release AEDT.
-
-# hfss.close_project()
-hfss.save_project()
-desktop.release_desktop()
diff --git a/examples/02-HFSS/Array.py b/examples/02-HFSS/Array.py
index ae3e31b95ce..a183d775d17 100644
--- a/examples/02-HFSS/Array.py
+++ b/examples/02-HFSS/Array.py
@@ -1,37 +1,34 @@
-"""
-HFSS: component antenna array
------------------------------
-This example shows how you can use PyAEDT to create an example using a 3D component file. It sets up
-the analysis, solves it, and uses postprocessing functions to create plots using Matplotlib and
-PyVista without opening the HFSS user interface. This examples runs only on Windows using CPython.
-"""
-##########################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: component antenna array
+
+# This example shows how you can use PyAEDT to create an example using a 3D component file. It sets up
+# the analysis, solves it, and uses postprocessing functions to create plots using Matplotlib and
+# PyVista without opening the HFSS user interface. This examples runs only on Windows using CPython.
+
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
from pyaedt.modules.solutions import FfdSolutionData
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-##########################################################
-# Download 3D component
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Download 3D component
+#
# Download the 3D component that is needed to run the example.
example_path = pyaedt.downloads.download_3dcomponent()
-##########################################################
-# Launch HFSS and save project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch HFSS and save project
+#
# Launch HFSS and save the project.
+
project_name = pyaedt.generate_unique_project_name(project_name="array")
hfss = pyaedt.Hfss(projectname=project_name,
specified_version="2023.2",
@@ -41,9 +38,8 @@
print("Project name " + project_name)
-##########################################################
-# Read array definition from JSON file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Read array definition from JSON file
+#
# Read the array definition from a JSON file. A JSON file
# can contain all information needed to import and set up a
# full array in HFSS.
@@ -57,9 +53,8 @@
dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"}
array = hfss.add_3d_component_array_from_json(dict_in)
-##########################################################
-# Modify cells
-# ~~~~~~~~~~~~
+# ## Modify cells
+#
# Make center element passive and rotate corner elements.
array.cells[1][1].is_active = False
@@ -68,9 +63,8 @@
array.cells[2][0].rotation = 90
array.cells[2][2].rotation = 90
-##########################################################
-# Set up simulation
-# ~~~~~~~~~~~~~~~~~
+# ## Set up simulation
+#
# Set up a simulation and analyze it.
setup = hfss.create_setup()
@@ -79,27 +73,24 @@
hfss.analyze(num_cores=4)
-##########################################################
-# Get far field data
-# ~~~~~~~~~~~~~~~~~~
+
+# ## Get far field data
+#
# Get far field data. After the simulation completes, the far
# field data is generated port by port and stored in a data class.
ffdata = hfss.get_antenna_ffd_solution_data(sphere_name="Infinite Sphere1", setup_name=hfss.nominal_adaptive,
frequencies=[5e9])
-
-##########################################################
-# Generate contour plot
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Generate contour plot
+#
# Generate a contour plot. You can define the Theta scan
# and Phi scan.
ffdata.plot_farfield_contour(farfield_quantity='RealizedGain',
title='Contour at {}Hz'.format(ffdata.frequency))
-##########################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
# Far field post-processing can be performed without AEDT because the data is stored.
@@ -109,25 +100,22 @@
hfss.release_desktop()
-##########################################################
-# Load far field data
-# ~~~~~~~~~~~~~~~~~~~
+# ## Load far field data
+#
# Load far field data stored.
ffdata = FfdSolutionData(frequencies=frequencies[0], eep_files=eep_file[0])
-##########################################################
-# Generate contour plot
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Generate contour plot
+#
# Generate a contour plot. You can define the Theta scan
# and Phi scan.
ffdata.plot_farfield_contour(farfield_quantity='RealizedGain',
title='Contour at {}Hz'.format(ffdata.frequency))
-##########################################################
-# Generate 2D cutout plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 2D cutout plots
+#
# Generate 2D cutout plots. You can define the Theta scan
# and Phi scan.
@@ -141,9 +129,8 @@
title='Elevation',
quantity_format="dB10")
-##########################################################
-# Generate 3D polar plots in Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 3D polar plots in Matplotlib
+#
# Generate 3D polar plots in Matplotlib. You can define
# the Theta scan and Phi scan.
diff --git a/examples/02-HFSS/Create_3d_Component_and_use_it.py b/examples/02-HFSS/Create_3d_Component_and_use_it.py
index 34958943383..c73af2cc590 100644
--- a/examples/02-HFSS/Create_3d_Component_and_use_it.py
+++ b/examples/02-HFSS/Create_3d_Component_and_use_it.py
@@ -1,83 +1,82 @@
-"""
-Create a 3D Component and reuse it
-----------------------------------
-Summary of the workflow
-1. Create an antenna using PyAEDT and HFSS 3D Modeler (same can be done with EDB and HFSS 3D Layout)
-2. Store the object as a 3D Component on the disk
-3. Reuse the 3D component in another project
-4. Parametrize and optimize target design
-"""
-
-##########################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Create a 3D Component and reuse it
+
+# Summary of the workflow
+# 1. Create an antenna using PyAEDT and HFSS 3D Modeler (same can be done with EDB and HFSS 3D Layout)
+# 2. Store the object as a 3D Component on the disk
+# 3. Reuse the 3D component in another project
+# 4. Parametrize and optimize target design
+
+# ## Perform required imports
+#
# Perform required imports.
+
import os
import tempfile
from pyaedt import Hfss
from pyaedt.generic.general_methods import generate_unique_name
-##########################################################
-# Launch HFSS 2023.2
-# ~~~~~~~~~~~~~~~~~~
+# ## Launch HFSS 2023.2
+#
# PyAEDT can initialize a new session of Electronics Desktop or connect to an existing one.
# Once Desktop is connected, a new HFSS session is started and a design is created.
hfss = Hfss(specified_version="2023.2", new_desktop_session=True, close_on_exit=True)
-##########################################################
-# Variables
-# ~~~~~~~~~
+# ## Variables
+#
# PyAEDT can create and store all variables available in AEDT (Design, Project, Post Processing)
hfss["thick"] = "0.1mm"
hfss["width"] = "1mm"
-##########################################################
-# Modeler
-# ~~~~~~~~
+# ## Modeler
+#
# PyAEDT supports all modeler functionalities available in the Desktop.
# Objects can be created, deleted and modified using all available boolean operations.
# History is also fully accessible to PyAEDT.
-substrate = hfss.modeler.create_box(["-width","-width","-thick"],["2*width","2*width", "thick"], matname="FR4_epoxy", name="sub")
+# +
+substrate = hfss.modeler.create_box(["-width","-width","-thick"],["2*width","2*width", "thick"],
+ matname="FR4_epoxy", name="sub")
-patch = hfss.modeler.create_rectangle("XY",["-width/2","-width/2","0mm"],["width","width"], name="patch1")
+patch = hfss.modeler.create_rectangle("XY",["-width/2","-width/2","0mm"],["width","width"],
+ name="patch1")
-via1 = hfss.modeler.create_cylinder(2, ["-width/8","-width/4","-thick"],"0.01mm", "thick", matname="copper", name="via_inner")
+via1 = hfss.modeler.create_cylinder(2, ["-width/8","-width/4","-thick"],"0.01mm", "thick",
+ matname="copper", name="via_inner")
-via_outer = hfss.modeler.create_cylinder(2, ["-width/8","-width/4","-thick"],"0.025mm", "thick", matname="Teflon_based", name="via_teflon")
+via_outer = hfss.modeler.create_cylinder(2, ["-width/8","-width/4","-thick"],"0.025mm", "thick",
+ matname="Teflon_based", name="via_teflon")
+# -
-##########################################################
-# Boundaries
-# ~~~~~~~~~~
+# ## Boundaries
+#
# Most of HFSS boundaries and excitations are already available in PyAEDT.
# User can assign easily a boundary to a face or to an object by taking benefits of
# Object-Oriented Programming (OOP) available in PyAEDT.
hfss.assign_perfecte_to_sheets(patch)
-##########################################################
-# Advanced Modeler functions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Thanks to Python capabilities a lot of additional functionalities have been added to the Modeler of PyAEDT.
-# in this example there is a property to retrieve automatically top and bottom faces of an objects.
+# ## Advanced Modeler functions
+#
+# Thanks to Python capabilities a lot of additional functionalities have been added to the modeler of PyAEDT.
+# In this example there is a property to retrieve automatically top and bottom faces of an objects.
+# +
side_face = [i for i in via_outer.faces if i.id not in [via_outer.top_face_z.id, via_outer.bottom_face_z.id]]
hfss.assign_perfecte_to_sheets(side_face)
hfss.assign_perfecte_to_sheets(substrate.bottom_face_z)
+# -
-##########################################################
-# Create Wave Port
-# ~~~~~~~~~~~~~~~~
+# ## Create Wave Port
+#
# Wave port can be assigned to a sheet or to a face of an object.
hfss.wave_port(via_outer.bottom_face_z, name="P1", )
-##########################################################
-# Create 3D Component
-# ~~~~~~~~~~~~~~~~~~~
+# ## Create 3D Component
+#
# Once the model is ready a 3D Component can be created.
# Multiple options are available to partially select objects, cs, boundaries and mesh operations.
# Furthermore, encrypted 3d comp can be created too.
@@ -85,52 +84,43 @@
component_path = os.path.join(tempfile.gettempdir(), generate_unique_name("component_test")+".aedbcomp")
hfss.modeler.create_3dcomponent(component_path, "patch_antenna")
-##########################################################
-# Multiple project management
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Multiple project management
+#
# PyAEDT allows to control multiple projects, design and solution type at the same time.
hfss2 = Hfss(projectname="new_project", designname="new_design")
-##########################################################
-# Insert of 3d component
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert of 3d component
+#
# The 3d component can be inserted without any additional info.
# All needed info will be read from the file itself.
hfss2.modeler.insert_3d_component(component_path)
-##########################################################
-# 3D Component Parameters
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## 3D Component Parameters
+#
# All 3d Component parameters are available and can be parametrized.
hfss2.modeler.user_defined_components["patch_antenna1"].parameters
-
hfss2["p_thick"] = "1mm"
-
hfss2.modeler.user_defined_components["patch_antenna1"].parameters["thick"]="p_thick"
-##########################################################
-# Multiple 3d Components
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Multiple 3d Components
+#
# There is no limit to the number of 3D components that can be added on the same design.
# They can be the same or linked to different files.
hfss2.modeler.create_coordinate_system(origin=[20, 20, 10], name="Second_antenna")
-
ant2 = hfss2.modeler.insert_3d_component(component_path, targetCS="Second_antenna")
-##########################################################
-# Move components
-# ~~~~~~~~~~~~~~~
+# ## Move components
+#
# The component can be moved by changing is position or moving the relative coordinate system.
hfss2.modeler.coordinate_systems[0].origin = [10, 10, 3]
-##########################################################
-# Boundaries
-# ~~~~~~~~~~
+# ## Boundaries
+#
# Most of HFSS boundaries and excitations are already available in PyAEDT.
# User can assign easily a boundary to a face or to an object by taking benefits of
@@ -142,22 +132,19 @@
# All setup parameters can be edited.
setup1 = hfss2.create_setup()
-
optim = hfss2.parametrics.add("p_thick", "0.2mm", "1.5mm", step=14)
-###############################################################################
-# Save project
-# ~~~~~~~~~~~~
+# ## Save project
+#
# Save the project.
hfss2.modeler.fit_all()
hfss2.plot(show=False, export_path=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
+# `pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing AEDT.
hfss2.save_project(os.path.join(tempfile.gettempdir(), generate_unique_name("parametrized")+".aedt"))
diff --git a/examples/02-HFSS/Flex_CPWG.py b/examples/02-HFSS/Flex_CPWG.py
index 65b473766da..51c2ea830f0 100644
--- a/examples/02-HFSS/Flex_CPWG.py
+++ b/examples/02-HFSS/Flex_CPWG.py
@@ -1,29 +1,24 @@
-"""
-HFSS: flex cable CPWG
----------------------
-This example shows how you can use PyAEDT to create a flex cable CPWG (coplanar waveguide with ground).
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: flex cable CPWG
+#
+# This example shows how you can use PyAEDT to create a flex cable CPWG (coplanar waveguide with ground).
+
+# ## Perform required imports
+#
# Perform required imports.
import os
from math import radians, sin, cos, sqrt
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
hfss = pyaedt.Hfss(specified_version="2023.2",
@@ -36,11 +31,11 @@
hfss.modeler.model_units = "mil"
hfss.mesh.assign_initial_mesh_from_slider(applycurvilinear=True)
-###############################################################################
-# Create variables
-# ~~~~~~~~~~~~~~~~
+# ## Create variables
+#
# Create input variables for creating the flex cable CPWG.
+# +
total_length = 300
theta = 120
r = 100
@@ -51,14 +46,14 @@
gnd_thickness = 2
xt = (total_length - r * radians(theta)) / 2
+# -
-
-###############################################################################
-# Create bend
-# ~~~~~~~~~~~
+# ## Create bend
+#
# Create the bend. The ``create_bending`` method creates a list of points for
# the bend based on the curvature radius and extension.
+# +
def create_bending(radius, extension=0):
position_list = [(-xt, 0, -radius), (0, 0, -radius)]
@@ -73,11 +68,10 @@ def create_bending(radius, extension=0):
position_list[-1] = (x, y, z)
return position_list
+# -
-
-###############################################################################
-# Draw signal line
-# ~~~~~~~~~~~~~~~~
+# ## Draw signal line
+#
# Draw a signal line to create a bent signal wire.
position_list = create_bending(r, 1)
@@ -89,11 +83,11 @@ def create_bending(radius, extension=0):
matname="copper",
)
-###############################################################################
-# Draw ground line
-# ~~~~~~~~~~~~~~~~
+# ## Draw ground line
+#
# Draw a ground line to create two bent ground wires.
+# +
gnd_r = [(x, spacing + width / 2 + gnd_width / 2, z) for x, y, z in position_list]
gnd_l = [(x, -y, z) for x, y, z in gnd_r]
@@ -104,12 +98,13 @@ def create_bending(radius, extension=0):
)
x.color = (255, 0, 0)
gnd_objs.append(x)
+# -
-###############################################################################
-# Draw dielectric
-# ~~~~~~~~~~~~~~~
+# ## Draw dielectric
+#
# Draw a dielectric to create a dielectric cable.
+# +
position_list = create_bending(r + (height + gnd_thickness) / 2)
fr4 = hfss.modeler.create_polyline(
@@ -119,12 +114,13 @@ def create_bending(radius, extension=0):
xsection_height=width + 2 * spacing + 2 * gnd_width,
matname="FR4_epoxy",
)
+# -
-###############################################################################
-# Create bottom metals
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Create bottom metals
+#
# Create the bottom metals.
+# +
position_list = create_bending(r + height + gnd_thickness, 1)
bot = hfss.modeler.create_polyline(
@@ -134,12 +130,13 @@ def create_bending(radius, extension=0):
xsection_height=width + 2 * spacing + 2 * gnd_width,
matname="copper",
)
+# -
-###############################################################################
-# Create port interfaces
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create port interfaces
+#
# Create port interfaces (PEC enclosures).
+# +
port_faces = []
for face, blockname in zip([fr4.top_face_z, fr4.bottom_face_x], ["b1", "b2"]):
xc, yc, zc = face.center
@@ -162,10 +159,10 @@ def create_bending(radius, extension=0):
i.subtract([port_block], True)
print(port_faces)
+# -
-###############################################################################
-# Create boundary condition
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create boundary condition
+#
# Creates a Perfect E boundary condition.
boundary = []
@@ -174,19 +171,19 @@ def create_bending(radius, extension=0):
boundary.append(s)
hfss.assign_perfecte_to_sheets(s)
-###############################################################################
-# Create ports
-# ~~~~~~~~~~~~
+# ## Create ports
+#
# Creates ports.
+# +
for s, port_name in zip(port_faces, ["1", "2"]):
reference = [i.name for i in gnd_objs + boundary + [bot]] + ["b1", "b2"]
hfss.wave_port(s.id, name=port_name, reference=reference)
+# -
-###############################################################################
-# Create setup and sweep
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and sweep
+#
# Create the setup and sweep.
setup = hfss.create_setup("setup1")
@@ -204,9 +201,8 @@ def create_bending(radius, extension=0):
sweep_type="Interpolating",
)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
my_plot = hfss.plot(show=False, plot_air_objects=False)
@@ -216,9 +212,8 @@ def create_bending(radius, extension=0):
os.path.join(hfss.working_directory, "Image.jpg"),
)
-###############################################################################
-# Analyze and release
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Analyze and release
+#
# Uncomment the ``hfss.analyze`` command if you want to analyze the
# model and release AEDT.
diff --git a/examples/02-HFSS/HFSS_Choke.py b/examples/02-HFSS/HFSS_Choke.py
index d6501bc473c..db2c2c54a20 100644
--- a/examples/02-HFSS/HFSS_Choke.py
+++ b/examples/02-HFSS/HFSS_Choke.py
@@ -1,30 +1,28 @@
-"""
-HFSS: choke
------------
-This example shows how you can use PyAEDT to create a choke setup in HFSS.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: choke
+#
+# This example shows how you can use PyAEDT to create a choke setup in HFSS.
+
+# ## Perform required imports
+#
# Perform required imports.
+# +
import json
import os
import pyaedt
project_name = pyaedt.generate_unique_project_name(project_name="choke")
+# -
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch HFSS
-# ~~~~~~~~~~~
+# ## Launch HFSS
+#
# Launches HFSS 2023 R2 in graphical mode.
hfss = pyaedt.Hfss(projectname=project_name,
@@ -33,9 +31,8 @@
new_desktop_session=True,
solution_type="Terminal")
-###############################################################################
-# Rules and information of use
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Rules and information of use
+#
# The dictionary values contain the different parameter values of the core and
# the windings that compose the choke. You must not change the main structure of
# the dictionary. The dictionary has many primary keys, including
@@ -43,7 +40,7 @@
# dictionaries as values. The keys of these dictionaries are secondary keys
# of the dictionary values, such as ``"1"``, ``"2"``, ``"3"``, ``"4"``, and
# ``"Simple"``.
-#
+#
# You must not modify the primary or secondary keys. You can modify only their values.
# You must not change the data types for these keys. For the dictionaries from
# ``"Number of Windings"`` through ``"Wire Section"``, values must be Boolean. Only
@@ -98,20 +95,17 @@
"Inner Winding": {"Turns": 4, "Coil Pit(deg)": 0.1, "Occupation(%)": 0},
}
-###############################################################################
-# Convert dictionary to JSON file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Convert dictionary to JSON file
+#
# Convert a dictionary to a JSON file. You must supply the path of the
# JSON file as an argument.
json_path = os.path.join(hfss.working_directory, "choke_example.json")
-
with open(json_path, "w") as outfile:
json.dump(values, outfile)
-###############################################################################
-# Verify parameters of JSON file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Verify parameters of JSON file
+#
# Verify parameters of the JSON file. The ``check_choke_values`` method takes
# the JSON file path as an argument and does the following:
#
@@ -121,10 +115,9 @@
dictionary_values = hfss.modeler.check_choke_values(json_path, create_another_file=False)
print(dictionary_values)
-###############################################################################
-# Create choke
-# ~~~~~~~~~~~~
-# Create the choke. The ``create_choke`` method takes the JSON file path as an
+# ## Create choke
+#
+# Create the choke. The ``Hfss.modeler.create_choke()`` method takes the JSON file path as an
# argument.
list_object = hfss.modeler.create_choke(json_path)
@@ -133,9 +126,8 @@
first_winding_list = list_object[2]
second_winding_list = list_object[3]
-###############################################################################
-# Create ground
-# ~~~~~~~~~~~~~
+# ## Create ground
+#
# Create a ground.
ground_radius = 1.2 * dictionary_values[1]["Outer Winding"]["Outer Radius"]
@@ -143,9 +135,8 @@
ground = hfss.modeler.create_circle("XY", ground_position, ground_radius, name="GND", matname="copper")
coat = hfss.assign_coating(ground, isinfgnd=True)
-###############################################################################
-# Create lumped ports
-# ~~~~~~~~~~~~~~~~~~~
+# ## Create lumped ports
+#
# Create lumped ports.
port_position_list = [
@@ -163,9 +154,8 @@
reference=[ground]
)
-###############################################################################
-# Create mesh
-# ~~~~~~~~~~~
+# ## Create mesh
+#
# Create the mesh.
cylinder_height = 2.5 * dictionary_values[1]["Outer Winding"]["Height"]
@@ -176,17 +166,15 @@
hfss.mesh.assign_length_mesh([mesh_operation_cylinder], maxlength=15, maxel=None, meshop_name="choke_mesh")
-###############################################################################
-# Create boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Create boundaries
+#
# Create the boundaries. A region with openings is needed to run the analysis.
region = hfss.modeler.create_region(pad_percent=1000)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup with a sweep to run the simulation. Depending on your machine's
# computing power, the simulation can take some time to run.
@@ -204,20 +192,18 @@
save_fields=False,
)
-###############################################################################
-# Save project
-# ~~~~~~~~~~~~
+# ## Save project
+#
# Save the project.
hfss.modeler.fit_all()
hfss.plot(show=False, export_path=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.release_desktop` method.
+# `pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
hfss.release_desktop()
diff --git a/examples/02-HFSS/HFSS_Dipole.py b/examples/02-HFSS/HFSS_Dipole.py
index 4b104b92e67..cb05bebec8d 100644
--- a/examples/02-HFSS/HFSS_Dipole.py
+++ b/examples/02-HFSS/HFSS_Dipole.py
@@ -1,12 +1,10 @@
-"""
-HFSS: dipole antenna
---------------------
-This example shows how you can use PyAEDT to create a dipole antenna in HFSS and postprocess results.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: dipole antenna
+#
+# This example shows how you can use PyAEDT to create a dipole antenna in HFSS
+# and postprocess results.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
@@ -14,38 +12,33 @@
project_name = pyaedt.generate_unique_project_name(project_name="dipole")
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. `
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
d = pyaedt.launch_desktop("2023.2", non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Launch HFSS
-# ~~~~~~~~~~~
+# ## Launch HFSS
+#
# Launch HFSS 2023 R2 in graphical mode.
hfss = pyaedt.Hfss(projectname=project_name, solution_type="Modal")
-###############################################################################
-# Define variable
-# ~~~~~~~~~~~~~~~
+# ## Define variable
+#
# Define a variable for the dipole length.
hfss["l_dipole"] = "13.5cm"
-###############################################################################
-# Get 3D component from system library
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get 3D component from system library
+#
# Get a 3D component from the ``syslib`` directory. For this example to run
# correctly, you must get all geometry parameters of the 3D component or, in
# case of an encrypted 3D component, create a dictionary of the parameters.
@@ -55,16 +48,14 @@
geometryparams["dipole_length"] = "l_dipole"
hfss.modeler.insert_3d_component(compfile, geometryparams)
-###############################################################################
-# Create boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Create boundaries
+#
# Create boundaries. A region with openings is needed to run the analysis.
hfss.create_open_region(Frequency="1GHz")
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
my_plot = hfss.plot(show=False, plot_air_objects=False)
@@ -75,9 +66,8 @@
os.path.join(hfss.working_directory, "Image.jpg"),
)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup with a sweep to run the simulation.
setup = hfss.create_setup("MySetup")
@@ -96,16 +86,14 @@
save_fields=False,
)
-###############################################################################
-# Save and run simulation
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save and run simulation
+#
# Save and run the simulation.
hfss.analyze_setup("MySetup")
-###############################################################################
-# Create scattering plot and far fields report
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create scattering plot and far fields report
+#
# Create a scattering plot and a far fields report.
hfss.create_scattering("MyScattering")
@@ -122,9 +110,8 @@
report_category="Far Fields",
)
-###############################################################################
-# Create far fields report using report objects
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create far fields report using report objects
+#
# Create a far fields report using the ``report_by_category.far field`` method,
# which gives you more freedom.
@@ -133,9 +120,8 @@
new_report.primary_sweep = "Theta"
new_report.create("Realized2D")
-###############################################################################
-# Generate multiple plots
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate multiple plots
+#
# Generate multiple plots using the object ``new_report``. This code generates
# 2D and 3D polar plots.
@@ -143,18 +129,16 @@
new_report.secondary_sweep = "Phi"
new_report.create("Realized3D")
-###############################################################################
-# Get solution data
-# ~~~~~~~~~~~~~~~~~
+# ## Get solution data
+#
# Get solution data using the object ``new_report``` and postprocess or plot the
# data outside AEDT.
solution_data = new_report.get_solution_data()
solution_data.plot()
-###############################################################################
-# Generate far field plot
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate far field plot
+#
# Generate a far field plot by creating a postprocessing variable and assigning
# it to a new coordinate system. You can use the ``post`` prefix to create a
# postprocessing variable directly from a setter, or you can use the ``set_variable``
@@ -165,9 +149,8 @@
hfss.modeler.create_coordinate_system(origin=["post_x", "y_post", 0], name="CS_Post")
hfss.insert_infinite_sphere(custom_coordinate_system="CS_Post", name="Sphere_Custom")
-###############################################################################
-# Get solution data
-# ~~~~~~~~~~~~~~~~~
+# ## Get solution data
+#
# Get solution data. You can use this code to generate the same plot outside AEDT.
new_report = hfss.post.reports_by_category.far_field("GainTotal", hfss.nominal_adaptive, "3D")
@@ -175,33 +158,29 @@
new_report.far_field_sphere = "3D"
solutions = new_report.get_solution_data()
-###############################################################################
-# Generate 3D plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 3D plot using Matplotlib
+#
# Generate a 3D plot using Matplotlib.
solutions.plot_3d()
-###############################################################################
-# Generate 3D far fields plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 3D far fields plot using Matplotlib
+#
# Generate a far fields plot using Matplotlib.
new_report.far_field_sphere = "Sphere_Custom"
solutions_custom = new_report.get_solution_data()
solutions_custom.plot_3d()
-###############################################################################
-# Generate 2D plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 2D plot using Matplotlib
+#
# Generate a 2D plot using Matplotlib where you specify whether it is a polar
# plot or a rectangular plot.
solutions.plot(math_formula="db20", is_polar=True)
-##########################################################
-# Get far field data
-# ~~~~~~~~~~~~~~~~~~
+# ## Get far field data
+#
# Get far field data. After the simulation completes, the far
# field data is generated port by port and stored in a data class, , user can use this data
# once AEDT is released.
@@ -209,9 +188,8 @@
ffdata = hfss.get_antenna_ffd_solution_data(sphere_name="Sphere_Custom", setup_name=hfss.nominal_adaptive,
frequencies=["1000MHz"])
-##########################################################
-# Generate 2D cutout plot
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate 2D cutout plot
+#
# Generate 2D cutout plot. You can define the Theta scan
# and Phi scan.
@@ -221,9 +199,8 @@
quantity_format="dB20",
is_polar=True)
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
diff --git a/examples/02-HFSS/HFSS_FSS_unitcell.py b/examples/02-HFSS/HFSS_FSS_unitcell.py
index 772b7dcf05c..2530d8648c6 100644
--- a/examples/02-HFSS/HFSS_FSS_unitcell.py
+++ b/examples/02-HFSS/HFSS_FSS_unitcell.py
@@ -1,71 +1,66 @@
-"""
-HFSS: FSS Unitcell Simulation
---------------------
-This example shows how you can use PyAEDT to create a FSS unitcell simulations in HFSS and postprocess results.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: FSS Unitcell Simulation
+#
+# This example shows how you can use PyAEDT to create a FSS unitcell simulations in HFSS and postprocess results.
+
+# ## Perform required imports
+#
# Perform required imports.
+# +
import os
import pyaedt
project_name = pyaedt.generate_unique_project_name(project_name="FSS")
+# -
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. `
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
d = pyaedt.launch_desktop("2023.2", non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Launch HFSS
-# ~~~~~~~~~~~
+# ## Launch HFSS
+#
# Launch HFSS 2023 R2 in graphical mode.
hfss = pyaedt.Hfss(projectname=project_name, solution_type="Modal")
-###############################################################################
-# Define variable
-# ~~~~~~~~~~~~~~~
+# ## Define variable
+#
# Define a variable for the 3D-component.
hfss["patch_dim"] = "10mm"
-###############################################################################
-# Insert 3D component from system library
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert 3D component from system library
+#
# Download the 3D component from the example data and insert the 3D Component.
+# +
unitcell_3d_component_path = pyaedt.downloads.download_FSS_3dcomponent()
unitcell_path = os.path.join(unitcell_3d_component_path, "FSS_unitcell_23R2.a3dcomp")
comp = hfss.modeler.insert_3d_component(unitcell_path)
+# -
-###############################################################################
-# Assign design parameter to 3D Component parameter
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign design parameter to 3D Component parameter
+#
# Assign parameter.
component_name = hfss.modeler.user_defined_component_names
comp.parameters["a"] = "patch_dim"
-###############################################################################
-# Create air region
-# ~~~~~~~~~~~~~~~~~
+# ## Create air region
+#
# Create an open region along +Z direction for unitcell analysis.
+# +
bounding_dimensions = hfss.modeler.get_bounding_dimension()
periodicity_x = bounding_dimensions[0]
@@ -77,17 +72,16 @@
)
[x_min, y_min, z_min, x_max, y_max, z_max] = region.bounding_box
+# -
-###############################################################################
-# Assign Lattice pair boundary
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign Lattice pair boundary
+#
# Assigning lattice pair boundary automatically detected.
hfss.auto_assign_lattice_pairs(object_to_assign=region.name)
-###############################################################################
-# Assign Floquet port excitation along +Z direction
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign Floquet port excitation along +Z direction
+#
# Assign Floquet port.
id_z_pos = region.top_face_z
@@ -95,9 +89,8 @@
portname='port_z_max', deembed_dist=10 * bounding_dimensions[2])
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup with a sweep to run the simulation.
setup = hfss.create_setup("MySetup")
@@ -115,11 +108,11 @@
save_fields=False,
)
-###############################################################################
-# Create S-parameter report using report objects
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create S-parameter report using report objects
+#
# Create S-parameter reports using create report.
+# +
all_quantities = hfss.post.available_report_quantities()
str_mag = []
str_ang = []
@@ -140,17 +133,16 @@
variations=variation,
plotname="phase_plot",
)
+# -
-###############################################################################
-# Save and run simulation
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save and run simulation
+#
# Save and run the simulation. Uncomment the line following line to run the analysis.
# hfss.analyze()
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
diff --git a/examples/02-HFSS/HFSS_Spiral.py b/examples/02-HFSS/HFSS_Spiral.py
index 5b5dc42099c..af9c1dff297 100644
--- a/examples/02-HFSS/HFSS_Spiral.py
+++ b/examples/02-HFSS/HFSS_Spiral.py
@@ -1,30 +1,27 @@
-"""
-HFSS: spiral inductor
----------------------
-This example shows how you can use PyAEDT to create a spiral inductor, solve it, and plot results.
-"""
-
-#############################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: spiral inductor
+#
+# This example shows how you can use PyAEDT to create a spiral inductor, solve it, and plot results.
+
+# ## Perform required imports
+#
# Perform required imports.
+# +
import os
import pyaedt
project_name = pyaedt.generate_unique_project_name(project_name="spiral")
+# -
-#############################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-#############################################################
-# Launch HFSS
-# ~~~~~~~~~~~
+# ## Launch HFSS
+#
# Launch HFSS 2023 R2 in non-graphical mode and change the
# units to microns.
@@ -32,9 +29,8 @@
hfss.modeler.model_units = "um"
p = hfss.modeler
-#############################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define input variables. You can use the values that follow or edit
# them.
@@ -47,9 +43,8 @@
gap = 3
hfss["Tsub"] = "6" + hfss.modeler.model_units
-#############################################################
-# Standardize polyline
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Standardize polyline
+#
# Standardize the polyline using the ``create_line`` method to fix
# the width, thickness, and material.
@@ -57,9 +52,8 @@ def create_line(pts):
p.create_polyline(pts, xsection_type="Rectangle", xsection_width=width, xsection_height=thickness, matname="copper")
-################################################################
-# Create spiral inductor
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create spiral inductor
+#
# Create the spiral inductor. This spiral inductor is not
# parametric, but you could parametrize it later.
@@ -75,9 +69,8 @@ def create_line(pts):
)
-################################################################
-# Center return path
-# ~~~~~~~~~~~~~~~~~~
+# ## Center return path
+#
# Center the return path.
x0, y0, z0 = ind.points[0]
@@ -87,9 +80,8 @@ def create_line(pts):
[width, width, gap + thickness],
matname="copper")
-################################################################
-# Create port 1
-# ~~~~~~~~~~~~~
+# ## Create port 1
+#
# Create port 1.
p.create_rectangle(csPlane=pyaedt.constants.PLANE.YZ,
@@ -99,9 +91,8 @@ def create_line(pts):
)
hfss.lumped_port(signal="port1", integration_line=pyaedt.constants.AXIS.Z)
-################################################################
-# Create port 2
-# ~~~~~~~~~~~~~
+# ## Create port 2
+#
# Create port 2.
create_line([(x1 + width / 2, y1, 0), (x1 - 5, y1, 0)])
@@ -110,11 +101,11 @@ def create_line(pts):
name="port2")
hfss.lumped_port(signal="port2", integration_line=pyaedt.constants.AXIS.Z)
-################################################################
-# Create silicon substrate and ground plane
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create silicon substrate and ground plane
+#
# Create the silicon substrate and the ground plane.
+# +
p.create_box([x1 - 20, x1 - 20, "-Tsub-{}{}/2".format(thickness, hfss.modeler.model_units)],
[-2 * x1 + 40, -2 * x1 + 40, "Tsub"],
matname="silicon")
@@ -122,12 +113,13 @@ def create_line(pts):
p.create_box([x1 - 20, x1 - 20, "-Tsub-{}{}/2".format(thickness, hfss.modeler.model_units)],
[-2 * x1 + 40, -2 * x1 + 40, -0.1],
matname="PEC")
+# -
-################################################################
-# Assign airbox and radiation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign airbox and radiation
+#
# Assign the airbox and the radiation.
+# +
box = p.create_box(
[x1 - 20, x1 - 20, "-Tsub-{}{}/2 - 0.1{}".format(thickness, hfss.modeler.model_units, hfss.modeler.model_units)],
[-2 * x1 + 40, -2 * x1 + 40, 100],
@@ -136,25 +128,23 @@ def create_line(pts):
)
hfss.assign_radiation_boundary_to_objects("airbox")
+# -
-################################################################
-# Assign material override
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign material override
+#
# Assign a material override so that the validation check does
# not fail.
hfss.change_material_override()
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
hfss.plot(show=False, export_path=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=False)
-################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create the setup and define a frequency sweep to solve the project.
setup1 = hfss.create_setup(setupname="setup1")
@@ -164,38 +154,34 @@ def create_line(pts):
hfss.save_project()
hfss.analyze()
-################################################################
-# Get report data
-# ~~~~~~~~~~~~~~~
+# ## Get report data
+#
# Get report data and use the following formulas to calculate
# the inductance and quality factor.
L_formula = "1e9*im(1/Y(1,1))/(2*pi*freq)"
Q_formula = "im(Y(1,1))/re(Y(1,1))"
-################################################################
-# Create output variable
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create output variable
+#
# Create output variable
+
hfss.create_output_variable("L", L_formula, solution="setup1 : LastAdaptive")
-################################################################
-# Plot calculated values in Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot calculated values in Matplotlib
+#
# Plot the calculated values in Matplotlib.
data = hfss.post.get_solution_data([L_formula, Q_formula])
data.plot(curves=[L_formula, Q_formula], math_formula="re", xlabel="Freq", ylabel="L and Q")
-################################################################
-# Export results to csv file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export results to csv file
+#
# Export results to csv file
data.export_data_to_csv(os.path.join(hfss.toolkit_directory,"output.csv"))
-################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
hfss.save_project(project_name)
diff --git a/examples/02-HFSS/HFSS_eigenmode.py b/examples/02-HFSS/HFSS_eigenmode.py
index 93d5e6bb671..443e490b1a1 100644
--- a/examples/02-HFSS/HFSS_eigenmode.py
+++ b/examples/02-HFSS/HFSS_eigenmode.py
@@ -1,34 +1,30 @@
-"""
-HFSS: Eigenmode filter
-----------------------
-This example shows how you can use PyAEDT to automate the eigenmode solver in HFSS.
-Eigenmode analysis can be applied to open, radiating structures
-using an absorbing boundary condition. This type of analysis is useful for
-determining the resonant frequency of a geometry or an antenna and can be used to refine
-the mesh at the resonance, even when the resonant frequency of the antenna is not known.
-
-The challenge posed by this method is to identify and filter the non-physical modes
-resulting from reflection from boundaries of the main domain.
-Because the Eigenmode solver sorts by frequency and does not filter on the
-quality factor, these virtual modes are present when the eigenmode approach is
-applied to nominally open structures.
-When looking for resonant modes over a wide frequency range for nominally
-enclosed structures, several iterations may be required because the minimum frequency
-is determined manually and simulations re-run until the complete frequency range is covered
-and all important physical modes are calculated.
-
-The following script finds the physical modes of a model in a wide frequency range by automating the solution setup.
-During each simulation, a user-defined number of modes is simulated, and the modes with a Q higher than a user- defined value are filtered.
-The next simulation automatically continues to find modes having a frequency higher than the last mode of the previous analysis.
-This continues until the maximum frequency in the desired range is achieved.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # HFSS: Eigenmode filter
+#
+# This example shows how you can use PyAEDT to automate the eigenmode solver in HFSS.
+# Eigenmode analysis can be applied to open, radiating structures
+# using an absorbing boundary condition. This type of analysis is useful for
+# determining the resonant frequency of a geometry or an antenna and can be used to refine
+# the mesh at the resonance, even when the resonant frequency of the antenna is not known.
+#
+# The challenge posed by this method is to identify and filter the non-physical modes
+# resulting from reflection from boundaries of the main domain.
+# Because the Eigenmode solver sorts by frequency and does not filter on the
+# quality factor, these virtual modes are present when the eigenmode approach is
+# applied to nominally open structures.
+# When looking for resonant modes over a wide frequency range for nominally
+# enclosed structures, several iterations may be required because the minimum frequency
+# is determined manually and simulations re-run until the complete frequency range is covered
+# and all important physical modes are calculated.
+#
+# The following script finds the physical modes of a model in a wide frequency range by automating the solution setup.
+# During each simulation, a user-defined number of modes is simulated, and the modes with a Q higher than a user- defined value are filtered.
+# The next simulation automatically continues to find modes having a frequency higher than the last mode of the previous analysis.
+# This continues until the maximum frequency in the desired range is achieved.
+
+# ## Perform required imports
+#
# Run through each cell. This cell imports the required packages.
-import sys
import os
import pyaedt
@@ -37,38 +33,33 @@
temp_folder = pyaedt.generate_unique_folder_name()
project_path = pyaedt.downloads.download_file("eigenmode", "emi_PCB_house.aedt", temp_folder)
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
desktop_version = "2023.2"
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
d = pyaedt.launch_desktop(desktop_version, non_graphical=non_graphical, new_desktop_session=True)
-###############################################################################
-# Launch HFSS
-# ~~~~~~~~~~~
+# ## Launch HFSS
+#
# Launch HFSS 2023 R2 in graphical mode.
hfss = pyaedt.Hfss(projectname=project_path, non_graphical=non_graphical)
-###############################################################################
-# Input parameters for eigenmode solver
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Input parameters for eigenmode solver
+#
# The geometry and material should be already set. The analyses are generated by the code.
# Number of modes during each analysis, max allowed number is 20.
# Entering a number higher than 10 might need long simulation time as the
@@ -76,6 +67,7 @@
# of interest. ``fmax`` is the highest frequency of interest.
# ``limit`` is the parameter limit that determines which modes are ignored.
+# +
num_modes = 6
fmin = 1
fmax = 2
@@ -84,15 +76,15 @@
limit = 10
resonance = {}
+# -
-
-###############################################################################
-# Find the modes
-# ~~~~~~~~~~~~~~
+# ## Find the modes
+#
# The following cell is a function. If called, it creates an eigenmode setup and solves it.
# After the solve, each mode, along with its corresponding real frequency and quality factor,
# are saved for further processing.
+# +
def find_resonance():
# setup creation
next_min_freq = str(next_fmin) + " GHz"
@@ -123,15 +115,15 @@ def find_resonance():
print(data)
return data
+# -
-
-###############################################################################
-# Automate eigenmode solution
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Automate eigenmode solution
+#
# Running the next cell calls the resonance function and saves only those modes with a Q higher than the defined
# limit. The ``find_resonance`` function is called until the complete frequency range is covered.
# When the automation ends, the physical modes in the whole frequency range are reported.
+# +
while next_fmin < fmax:
output = find_resonance()
next_fmin = output[len(output) - 1][1] / 1e9
@@ -144,18 +136,17 @@ def find_resonance():
resonance_frequencies = [f"{resonance[i][1] / 1e9:.5} GHz" for i in resonance]
print(str(resonance_frequencies))
+# -
-###############################################################################
-# Save project
-# ~~~~~~~~~~~~
+# ## Save project
+#
# Save the project.
hfss.modeler.fit_all()
hfss.plot(show=False, export_path=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=False)
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
hfss.save_project()
diff --git a/examples/02-HFSS/Probe_Fed_Patch.py b/examples/02-HFSS/Probe_Fed_Patch.py
index 13b377d7c7d..3ed10cd890c 100644
--- a/examples/02-HFSS/Probe_Fed_Patch.py
+++ b/examples/02-HFSS/Probe_Fed_Patch.py
@@ -1,26 +1,20 @@
-"""
-HFSS: Probe-fed patch antenna
----------------------------------------------------------
-This example shows how to use the ``Stackup3D`` class
-to create and analyze a patch antenna in HFSS.
-
-Note that the HFSS 3D Layout interface may offer advantages for
-laminate structures such as the patch antenna.
-"""
+# # HFSS: Probe-fed patch antenna
+#
+# This example shows how to use the ``Stackup3D`` class
+# to create and analyze a patch antenna in HFSS.
+#
+# Note that the HFSS 3D Layout interface may offer advantages for
+# laminate structures such as the patch antenna.
-###########################
-# Perform imports
-# ~~~~~~~~~~~~~~~~~~
+# ## Perform imports
import os
-
import pyaedt
import tempfile
from pyaedt.modeler.advanced_cad.stackup_3d import Stackup3D
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. ``"PYAEDT_NON_GRAPHICAL"`` is set to ``False``
# to create this documentation.
#
@@ -34,9 +28,8 @@
length_units = "mm"
freq_units = "GHz"
-########################################################
-# Create temporary working folder
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create temporary working folder
+#
# Use tempfile to create a temporary working folder. Project data
# is deleted after this example is run.
#
@@ -51,11 +44,9 @@
project_folder = tmpdir.name
proj_name = os.path.join(project_folder, "antenna")
-#####################
-# Launch HFSS
-# -----------
-#
+# ## Launch HFSS
+# +
hfss = pyaedt.Hfss(projectname=proj_name,
solution_type="Terminal",
designname="patch",
@@ -63,13 +54,14 @@
specified_version=desktop_version)
hfss.modeler.model_units = length_units
+# -
-#####################################
-# Create patch
-# ------------
-# Create the patch.
+# ## Create patch
#
+# Create the patch.
+
+# +
stackup = Stackup3D(hfss)
ground = stackup.add_ground_layer("ground", material="copper", thickness=0.035, fill_material="air")
dielectric = stackup.add_dielectric_layer("dielectric", thickness="0.5" + length_units, material="Duroid (tm)")
@@ -95,19 +87,18 @@
hfss.save_project()
hfss.analyze()
+# -
-###############################
-# Plot S11
-# ---------
+# ## Plot S11
+#
plot_data = hfss.get_traces_for_plot()
report = hfss.post.create_report(plot_data)
solution = report.get_solution_data()
plt = solution.plot(solution.expressions)
-###############################################################################
-# Release AEDT
-# ------------
+# ## Release AEDT
+#
# Release AEDT and clean up temporary folders and files.
hfss.release_desktop()
diff --git a/examples/02-HFSS/Readme.txt b/examples/02-HFSS/Readme.txt
deleted file mode 100644
index 9f03c21f896..00000000000
--- a/examples/02-HFSS/Readme.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-HFSS examples
-~~~~~~~~~~~~~
-These examples use PyAEDT to show some end-to-end workflows for HFSS 3D.
-This includes model generation, setup, meshing, and postprocessing.
diff --git a/examples/02-HFSS/Waveguide_Filter.py b/examples/02-HFSS/Waveguide_Filter.py
index 9624c0f21c3..a082b2ca2c1 100644
--- a/examples/02-HFSS/Waveguide_Filter.py
+++ b/examples/02-HFSS/Waveguide_Filter.py
@@ -1,16 +1,12 @@
-"""
-HFSS: Inductive Iris waveguide filter
--------------------------------------
-This example shows how to build and analyze a 4-pole
-X-Band waveguide filter using inductive irises.
-
-"""
+# # HFSS: Inductive Iris waveguide filter
+#
+# This example shows how to build and analyze a 4-pole
+# X-Band waveguide filter using inductive irises.
-# sphinx_gallery_thumbnail_path = 'Resources/wgf.png'
+#
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports.
#
@@ -19,15 +15,10 @@
import pyaedt
from pyaedt import general_methods
-###############################################################################
-# Launch Ansys Electronics Desktop (AEDT)
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#
-
+# ## Launch Ansys Electronics Desktop (AEDT)
-###############################################################################
-# Define parameters and values for waveguide iris filter
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Define parameters and values for waveguide iris filter
+#
# l: Length of the cavity from the mid-point of one iris
# to the midpoint of the next iris.
# w: Width of the iris opening.
@@ -35,6 +26,7 @@
# b: Short dimension of the waveguide cross-section.
# t: Metal thickness of the iris insert.
+# +
wgparams = {'l': [0.7428, 0.82188],
'w': [0.50013, 0.3642, 0.3458],
'a': 0.4,
@@ -44,10 +36,9 @@
non_graphical = False
new_thread = True
+# -
-###############################################################################
-# Save the project and results in the TEMP folder
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Save the project and results in the TEMP folder
project_folder = os.path.join(tempfile.gettempdir(), "waveguide_example")
if not os.path.exists(project_folder):
@@ -55,6 +46,7 @@
project_name = os.path.join(project_folder, general_methods.generate_unique_name("wgf", n=2))
# Instantiate the HFSS application
+
hfss = pyaedt.Hfss(projectname=project_name + '.aedt',
specified_version="2023.2",
designname="filter",
@@ -66,10 +58,9 @@
var_mapping = dict() # Used by parse_expr to parse expressions.
-###############################################################################
-# Initialize design parameters in HFSS.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Initialize design parameters in HFSS.
+# +
hfss.modeler.model_units = "in" # Set to inches
for key in wgparams:
if type(wgparams[key]) in [int, float]:
@@ -89,11 +80,10 @@
else:
zstart = "l1/2 - t/2" # Odd number of cavities, even number of irises.
is_even = False
+# -
-
-###############################################################################
-# Draw parametric waveguide filter
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Draw parametric waveguide filter
+#
# Define a function to place each iris at the correct longitudinal (z) position,
# Loop from the largest index (interior of the filter) to 1, which is the first
# iris nearest the waveguide ports.
@@ -109,12 +99,11 @@ def place_iris(zpos, dz, n):
iris.append(iris[0].mirror([0, 0, 0], [1, 0, 0], duplicate=True))
return iris
-
-###############################################################################
-# Place irises
-# ~~~~~~~~~~~~
+# ### Place irises
+#
# Place the irises from inner (highest integer) to outer.
+# +
for count in reversed(range(1, len(wgparams['w']) + 1)):
if count < len(wgparams['w']): # Update zpos
zpos = zpos + "".join([" + l" + str(count) + " + "])[:-3]
@@ -126,10 +115,10 @@ def place_iris(zpos, dz, n):
iris = place_iris(zpos, "t", count)
if not is_even:
iris = place_iris("-(" + zpos + ")", "-t", count)
+# -
-###############################################################################
-# Draw full waveguide with ports
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Draw full waveguide with ports
+#
# Use ``hfss.variable_manager`` which acts like a dict() to return an instance of
# the ``pyaedt.application.Variables.VariableManager`` class for any variable.
# The ``VariableManager`` instance takes the HFSS variable name as a key.
@@ -147,21 +136,19 @@ def place_iris(zpos, dz, n):
hfss.modeler.create_box(["-b/2", "-a/2", "wg_z_start"], ["b", "a", "wg_length"],
name="waveguide", matname="vacuum")
-###############################################################################
-# Draw the whole waveguide.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Draw the whole waveguide.
+#
# wg_z is the total length of the waveguide, including port extension.
# Note that the ``.evaluated_value`` provides access to the numerical value of
# ``wg_z_start`` which is an expression in HFSS.
wg_z = [wg_z_start.evaluated_value, hfss.value_with_units(wg_z_start.numeric_value + wg_length.numeric_value, "in")]
-###############################################################################
-# Assign wave ports to the end faces of the waveguid
+# Assign wave ports to the end faces of the waveguide
# and define the calibration lines to ensure self-consistent
# polarization between wave ports.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# +
count = 0
ports = []
for n, z in enumerate(wg_z):
@@ -170,15 +157,16 @@ def place_iris(zpos, dz, n):
u_end = [0, hfss.variable_manager["u_end"].evaluated_value, z]
ports.append(hfss.wave_port(face_id, integration_line=[u_start, u_end], name="P" + str(n + 1), renormalize=False))
+# -
-###############################################################################
-# Insert the mesh adaptation setup using refinement at two frequencies.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Insert the mesh adaptation setup using refinement at two frequencies.
+#
# This approach is useful for resonant structures as the coarse initial
# mesh impacts the resonant frequency and hence, the field propagation through the
# filter. Adaptation at multiple frequencies helps to ensure that energy propagates
# through the resonant structure while the mesh is refined.
+# +
setup = hfss.create_setup("Setup1", setuptype="HFSSDriven",
MultipleAdaptiveFreqsSetup=['9.8GHz', '10.2GHz'],
MaximumPasses=5)
@@ -190,31 +178,31 @@ def place_iris(zpos, dz, n):
freqstop=10.5,
sweep_type="Interpolating",
)
+# -
-#################################################################################
# Solve the project with two tasks.
# Each frequency point is solved simultaneously.
setup.analyze(num_tasks=2)
-###############################################################################
-# Generate S-Parameter Plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Generate S-Parameter Plots
+#
# The following commands fetch solution data from HFSS for plotting directly
# from the Python interpreter.
# Caution: The syntax for expressions must be identical to that used
# in HFSS.
+# +
traces_to_plot = hfss.get_traces_for_plot(second_element_filter="P1*")
report = hfss.post.create_report(traces_to_plot) # Creates a report in HFSS
solution = report.get_solution_data()
plt = solution.plot(solution.expressions) # Matplotlib axes object.
+# -
-###############################################################################
-# Generate E field plot
-# ~~~~~~~~~~~~~~~~~~~~~
+# ### Generate E field plot
+#
# The following command generates a field plot in HFSS and uses PyVista
# to plot the field in Jupyter.
@@ -226,9 +214,8 @@ def place_iris(zpos, dz, n):
export_path=hfss.working_directory,
show=False)
-###############################################################################
-# Save and close the desktop
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Save and close the desktop
+#
# The following command saves the project to a file and closes the desktop.
hfss.save_project()
diff --git a/doc/source/Resources/wgf.png b/examples/02-HFSS/_static/wgf.png
similarity index 100%
rename from doc/source/Resources/wgf.png
rename to examples/02-HFSS/_static/wgf.png
diff --git a/examples/02-HFSS/index.rst b/examples/02-HFSS/index.rst
new file mode 100644
index 00000000000..75907a9834a
--- /dev/null
+++ b/examples/02-HFSS/index.rst
@@ -0,0 +1,17 @@
+HFSS examples
+~~~~~~~~~~~~~
+These examples use PyAEDT to show some end-to-end workflows for HFSS 3D.
+This includes model generation, setup, meshing, and postprocessing.
+
+.. nbgallery::
+
+ Array.py
+ Create_3d_Component_and_use_it.py
+ Flex_CPWG.py
+ HFSS_Choke.py
+ HFSS_Dipole.py
+ HFSS_eigenmode.py
+ HFSS_FSS_unitcell.py
+ HFSS_Spiral.py
+ Probe_Fed_Patch.py
+ Waveguide_Filter.py
diff --git a/examples/02-SBR+/SBR_City_Import.py b/examples/02-SBR+/SBR_City_Import.py
index 88b66b020a1..fdc9912da79 100644
--- a/examples/02-SBR+/SBR_City_Import.py
+++ b/examples/02-SBR+/SBR_City_Import.py
@@ -1,29 +1,25 @@
-"""
-SBR+: Import Geometry from Maps
--------------------------------
-This example shows how you can use PyAEDT to create an HFSS SBR+ project from an
-OpenStreeMaps.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # SBR+: Import Geometry from Maps
+#
+# This example shows how you can use PyAEDT to create an HFSS SBR+ project from an
+# OpenStreeMaps.
+
+# ## Perform required imports
+#
# Perform required imports and set up the local path to the PyAEDT
# directory path.
import os
from pyaedt import Hfss
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Define designs
-# ~~~~~~~~~~~~~~
+# ## Define designs
+#
# Define two designs, one source and one target.
# Each design is connected to a different object.
@@ -35,15 +31,13 @@
non_graphical=non_graphical
)
-###############################################################################
-# Define Location to import
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define Location to import
+#
# Define latitude and longitude to import.
ansys_home = [40.273726, -80.168269]
-###############################################################################
-# Generate map and import
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate map and import
+#
# Assign boundaries.
app.modeler.import_from_openstreet_map(ansys_home,
@@ -52,9 +46,8 @@
plot_before_importing=False,
import_in_aedt=True)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
plot_obj = app.plot(show=False, plot_air_objects=True)
@@ -65,9 +58,8 @@
plot_obj.bounding_box = False
plot_obj.plot(os.path.join(app.working_directory, "Source.jpg"))
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT and close the example.
app.release_desktop()
diff --git a/examples/02-SBR+/SBR_Doppler_Example.py b/examples/02-SBR+/SBR_Doppler_Example.py
index 07a015299d6..d208ae73e73 100644
--- a/examples/02-SBR+/SBR_Doppler_Example.py
+++ b/examples/02-SBR+/SBR_Doppler_Example.py
@@ -1,20 +1,17 @@
-"""
-SBR+: doppler setup
--------------------
-This example shows how you can use PyAEDT to create a multipart scenario in HFSS SBR+
-and set up a doppler analysis.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # SBR+: doppler setup
+#
+# This example shows how you can use PyAEDT to create a multipart scenario in HFSS SBR+
+# and set up a doppler analysis.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT.
aedt_version = "2023.2"
@@ -22,17 +19,15 @@
designname = "doppler"
library_path = pyaedt.downloads.download_multiparts()
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Download and open project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download and open project
+#
# Download and open the project.
project_name = pyaedt.generate_unique_project_name(project_name="doppler")
@@ -49,17 +44,15 @@
app.autosave_disable()
-###############################################################################
-# Save project and rename design
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and rename design
+#
# Save the project to the temporary folder and rename the design.
app.save_project()
app.rename_design(designname)
-###############################################################################
-# Set up library paths
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Set up library paths
+#
# Set up library paths to 3D components.
actor_lib = os.path.join(library_path, "actor_library")
@@ -71,17 +64,15 @@
bike_folder = os.path.join(actor_lib, "bike1")
bird_folder = os.path.join(actor_lib, "bird1")
-###############################################################################
-# Define environment
-# ~~~~~~~~~~~~~~~~~~
+# ## Define environment
+#
# Define the background environment.
road1 = app.modeler.add_environment(env_folder=env_folder, environment_name="Bari")
prim = app.modeler
-###############################################################################
-# Place actors
-# ~~~~~~~~~~~~
+# ## Place actors
+#
# Place actors in the environment. This code places persons, birds, bikes, and cars
# in the environment.
@@ -108,9 +99,8 @@
actor_folder=bird_folder, speed=1.0, global_offset=[6, 2, 3], yaw=-60, pitch=10, actor_name="Eagle"
)
-###############################################################################
-# Place radar
-# ~~~~~~~~~~~
+# ## Place radar
+#
# Place radar on the car. The radar is created relative to the car's coordinate
# system.
@@ -122,9 +112,8 @@
relative_cs_name=car1.cs_name,
)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create setup and validate it. The ``create_sbr_pulse_doppler_setup`` method
# creates a setup and a parametric sweep on the time variable with a
# duration of two seconds. The step is computed automatically from CPI.
@@ -133,16 +122,14 @@
app.set_sbr_current_sources_options()
app.validate_simple()
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
app.plot(show=False, export_path=os.path.join(app.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Solve and release AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Solve and release AEDT
+#
# Solve and release AEDT. To solve, uncomment the ``app.analyze_setup`` command
# to activate the simulation.
diff --git a/examples/02-SBR+/SBR_Example.py b/examples/02-SBR+/SBR_Example.py
index 4616973cd06..1ee324ab159 100644
--- a/examples/02-SBR+/SBR_Example.py
+++ b/examples/02-SBR+/SBR_Example.py
@@ -1,12 +1,10 @@
-"""
-SBR+: HFSS to SBR+ coupling
----------------------------
-This example shows how you can use PyAEDT to create an HFSS SBR+ project from an
-HFSS antenna and run a simulation.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # SBR+: HFSS to SBR+ coupling
+#
+# This example shows how you can use PyAEDT to create an HFSS SBR+ project from an
+# HFSS antenna and run a simulation.
+
+# ## Perform required imports
+#
# Perform required imports and set up the local path to the path for the PyAEDT
# directory.
@@ -15,20 +13,19 @@
project_full_name = pyaedt.downloads.download_sbr(pyaedt.generate_unique_project_name(project_name="sbr_freq"))
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Define designs
-# ~~~~~~~~~~~~~~
+# ## Define designs
+#
# Define two designs, one source and one target, with each design connected to
# a different object.
+# +
target = pyaedt.Hfss(
projectname=project_full_name,
designname="Cassegrain_",
@@ -42,33 +39,30 @@
designname="feeder",
specified_version="2023.2",
)
+# -
-###############################################################################
-# Define linked antenna
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define linked antenna
+#
# Define a linked antenna. This is HFSS far field applied to HFSS SBR+.
target.create_sbr_linked_antenna(source, target_cs="feederPosition", fieldtype="farfield")
-###############################################################################
-# Assign boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Assign boundaries
+#
# Assign boundaries.
target.assign_perfecte_to_sheets(["Reflector", "Subreflector"])
target.mesh.assign_curvilinear_elements(["Reflector", "Subreflector"])
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model
source.plot(show=False, export_path=os.path.join(target.working_directory, "Source.jpg"), plot_air_objects=True)
target.plot(show=False, export_path=os.path.join(target.working_directory, "Target.jpg"), plot_air_objects=False)
-###############################################################################
-# Create setup and solve
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and solve
+#
# Create a setup and solve it.
setup1 = target.create_setup()
@@ -80,9 +74,8 @@
setup1["RangeStart"] = "10GHz"
target.analyze()
-###############################################################################
-# Plot results
-# ~~~~~~~~~~~~
+# ## Plot results
+#
# Plot results.
variations = target.available_variations.nominal_w_values_dict
@@ -98,9 +91,8 @@
report_category="Far Fields",
)
-###############################################################################
-# Plot results outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot results outside AEDT
+#
# Plot results using Matplotlib.
solution = target.post.get_solution_data(
@@ -113,9 +105,8 @@
)
solution.plot()
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT and close the example.
target.release_desktop()
diff --git a/examples/02-SBR+/SBR_Time_Plot.py b/examples/02-SBR+/SBR_Time_Plot.py
index c227f3ee99f..780555c4e69 100644
--- a/examples/02-SBR+/SBR_Time_Plot.py
+++ b/examples/02-SBR+/SBR_Time_Plot.py
@@ -1,40 +1,36 @@
-"""
-SBR+: HFSS to SBR+ time animation
----------------------------------
-This example shows how you can use PyAEDT to create an SBR+ time animation
-and save it to a GIF file. This example works only on CPython.
-"""
-
-###############################################################################
-# Perform required imports.
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# # SBR+: HFSS to SBR+ time animation
+#
+# This example shows how you can use PyAEDT to create an SBR+ time animation
+# and save it to a GIF file. This example works only on CPython.
+
+# ## Perform required imports.
+#
# Perform required imports.
import os
from pyaedt import Hfss, downloads
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT and load project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and load project
+#
# Launch AEDT and load the project.
+# +
project_file = downloads.download_sbr_time()
hfss = Hfss(projectname=project_file, specified_version="2023.2", non_graphical=non_graphical, new_desktop_session=True)
hfss.analyze()
+# -
-###############################################################################
-# Get solution data
-# ~~~~~~~~~~~~~~~~~
+# ## Get solution data
+#
# Get solution data. After simulation is performed, you can load solutions
# in the ``solution_data`` object.
@@ -43,27 +39,25 @@
context="Near_Field",
report_category="Near Fields")
-###############################################################################
-# Compute IFFT
-# ~~~~~~~~~~~~
+# ## Compute IFFT
+#
# Compute IFFT (Inverse Fast Fourier Transform).
t_matrix = solution_data.ifft("NearE", window=True)
-###############################################################################
-# Export IFFT to CSV file
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export IFFT to CSV file
+#
# Export IFFT to a CSV file.
frames_list_file = solution_data.ifft_to_file(coord_system_center=[-0.15, 0, 0], db_val=True,
csv_dir=os.path.join(hfss.working_directory, "csv"))
-###############################################################################
-# Plot scene
-# ~~~~~~~~~~
+# ## Plot scene
+#
# Plot the scene to create the time plot animation
+# +
hfss.post.plot_scene(frames_list=frames_list_file,
output_gif_path=os.path.join(hfss.working_directory, "animation.gif"),
norm_index=15,
@@ -71,3 +65,4 @@
show=False, view="xy", zoom=1)
hfss.release_desktop()
+# -
\ No newline at end of file
diff --git a/examples/02-SBR+/Readme.txt b/examples/02-SBR+/index.rst
similarity index 61%
rename from examples/02-SBR+/Readme.txt
rename to examples/02-SBR+/index.rst
index edb3b62f744..d6a3be8fdc9 100644
--- a/examples/02-SBR+/Readme.txt
+++ b/examples/02-SBR+/index.rst
@@ -2,3 +2,10 @@ SBR+ examples
~~~~~~~~~~~~~
These examples use PyAEDT to show some end-to-end workflows for HFSS SBR+.
This includes model generation, setup, meshing, and postprocessing.
+
+.. nbgallery::
+
+ SBR_City_Import.py
+ SBR_Doppler_Example.py
+ SBR_Example.py
+ SBR_Time_Plot.py
diff --git a/examples/03-Maxwell/Maxwell2D_DCConduction.py b/examples/03-Maxwell/Maxwell2D_DCConduction.py
index 7b461b51ea3..4f1ab90b276 100644
--- a/examples/03-Maxwell/Maxwell2D_DCConduction.py
+++ b/examples/03-Maxwell/Maxwell2D_DCConduction.py
@@ -1,19 +1,15 @@
-"""
-Maxwell 2D: resistance calculation
-----------------------------------
-This example uses PyAEDT to set up a resistance calculation
-and solve it using the Maxwell 2D DCConduction solver.
-Keywords: DXF import, material sweep, expression cache
-"""
-import os.path
+# # Maxwell 2D: resistance calculation
-import pyaedt
+# This example uses PyAEDT to set up a resistance calculation
+# and solve it using the Maxwell 2D DCConduction solver.
+# Keywords: DXF import, material sweep, expression cache
+import os.path
+import pyaedt
from pyaedt.generic.pdf import AnsysReport
-##################################################################################
-# Launch AEDT and Maxwell 2D
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and Maxwell 2D
+#
# Launch AEDT and Maxwell 2D after first setting up the project and design names,
# the solver, and the version. The following code also creates an instance of the
# ``Maxwell2d`` class named ``m2d``.
@@ -27,34 +23,33 @@
designname="Ansys_resistor"
)
-##########################################################
-# Create results folder
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Create results folder
+#
# Create results folder.
results_folder = os.path.join(m2d.working_directory, "M2D_DC_Conduction")
if not os.path.exists(results_folder):
os.mkdir(results_folder)
-##################################################################################
-# Import geometry as a DXF file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import geometry as a DXF file
+#
# You can test importing a DXF or a Parasolid file by commenting/uncommenting
# the following lines.
# Importing DXF files only works in graphical mode.
+# +
# DXFPath = pyaedt.downloads.download_file("dxf", "Ansys_logo_2D.dxf")
# dxf_layers = m2d.get_dxf_layers(DXFPath)
# m2d.import_dxf(DXFPath, dxf_layers, scale=1E-05)
ParasolidPath = pyaedt.downloads.download_file("x_t", "Ansys_logo_2D.x_t")
m2d.modeler.import_3d_cad(ParasolidPath)
+# -
-##################################################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define conductor thickness in z-direction, material array with 4 materials,
-# and MaterialIndex referring to the material array
+# and MaterialIndex referring to the material array.
m2d["MaterialThickness"] = "5mm"
m2d["ConductorMaterial"] = "[\"Copper\", \"Aluminum\", \"silver\", \"gold\"]"
@@ -62,41 +57,35 @@
m2d["MaterialIndex"] = str(MaterialIndex)
no_materials = 4
-
-##################################################################################
-# Assign materials
-# ~~~~~~~~~~~~~~~~
+# ## Assign materials
+#
# Voltage ports will be defined as perfect electric conductor (pec), conductor
-# gets the material defined by the 0th entry of the material array
+# gets the material defined by the 0th entry of the material array.
m2d.assign_material(["ANSYS_LOGO_2D_1", "ANSYS_LOGO_2D_2"], "pec")
m2d.modeler["ANSYS_LOGO_2D_3"].material_name = "ConductorMaterial[MaterialIndex]"
-##################################################################################
-# Assign voltages
-# ~~~~~~~~~~~~~~~
-# 1V and 0V
+# ## Assign voltages
+#
+# 1V and 0V.
m2d.assign_voltage(["ANSYS_LOGO_2D_1"], amplitude=1, name="1V")
m2d.assign_voltage(["ANSYS_LOGO_2D_2"], amplitude=0, name="0V")
-##################################################################################
-# Setup conductance calculation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# 1V is the source, 0V ground
+# ## Setup conductance calculation
+#
+# 1V is the source, 0V ground.
m2d.assign_matrix(sources=['1V'], group_sources=['0V'], matrix_name="Matrix1")
-##################################################################################
-# Assign mesh operation
-# ~~~~~~~~~~~~~~~~~~~~~
-# 3mm on the conductor
+# ## Assign mesh operation
+#
+# 3mm on the .
m2d.mesh.assign_length_mesh(["ANSYS_LOGO_2D_3"], meshop_name="conductor", maxlength=3, maxel=None)
-##################################################################################
-# Create simulation setup and enable expression cache
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create simulation setup and enable expression cache
+#
# Create simulation setup with minimum 4 adaptive passes to ensure convergence.
# Enable expression cache to observe the convergence.
@@ -109,9 +98,8 @@
use_cache_for_freq=False)
setup1.analyze()
-##################################################################################
-# Create parametric sweep
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create parametric sweep
+#
# Create parametric sweep to sweep all the entries in the material array.
# Save fields and mesh and use the mesh for all the materials.
@@ -123,11 +111,11 @@
param_sweep["SolveWithCopiedMeshOnly"] = True
param_sweep.analyze()
-##################################################################################
-# Create resistance report
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Create R. vs. material report
+# ## Create resistance report
+#
+# Create R. vs. material report.
+# +
variations = {"MaterialIndex": ["All"], "MaterialThickness": ["Nominal"]}
report = m2d.post.create_report(
expressions="1/Matrix1.G(1V,1V)/MaterialThickness",
@@ -148,20 +136,19 @@
for i in range(len(d.primary_sweep_values)):
material_index_vs_resistance.append([str(d.primary_sweep_values[i]), str(resistence[i])])
colors.append([None, None])
+# -
-##################################################################################
-# Field overlay
-# ~~~~~~~~~~~~~
-# Plot electric field and current density on the conductor surface
+# ## Field overlay
+#
+# Plot electric field and current density on the conductor surface.
conductor_surface = m2d.modeler["ANSYS_LOGO_2D_3"].faces
plot1 = m2d.post.create_fieldplot_surface(conductor_surface, "Mag_E", plot_name="Electric Field")
plot2 = m2d.post.create_fieldplot_surface(conductor_surface, "Mag_J", plot_name="Current Density")
-##################################################################################
-# Field overlay
-# ~~~~~~~~~~~~~
-# Plot electric field using pyvista and saving to an image
+# ## Field overlay
+#
+# Plot electric field using pyvista and saving to an image.
py_vista_plot = m2d.post.plot_field("Mag_E", conductor_surface, plot_cad_objs=False, show=False)
py_vista_plot.isometric_view = False
@@ -172,9 +159,8 @@
py_vista_plot.azimuth_angle = 0
py_vista_plot.plot(os.path.join(results_folder, "mag_E.jpg"))
-##################################################################################
-# Field animation
-# ~~~~~~~~~~~~~~~
+# ## Field animation
+#
# Plot current density vs the Material index.
animated = m2d.post.plot_animated_field(
@@ -195,16 +181,14 @@
animated.azimuth_angle = 0
animated.animate()
-################################################################################
-# Export model picture
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Export model picture
+#
# Export model picture.
model_picture = m2d.post.export_model_picture()
-################################################################################
-# Generate PDF report
-# ~~~~~~~~~~~~~~~~~~~
+# ## Generate PDF report
+#
# Generate a PDF report with output of simulation.
pdf_report = AnsysReport(project_name=m2d.project_name, design_name=m2d.design_name, version="2023.2")
@@ -233,7 +217,6 @@
pdf_report.add_toc()
pdf_report.save_pdf(results_folder, "AEDT_Results.pdf")
-##################################################################################
-# Release desktop
-# ~~~~~~~~~~~~~~~
+# ## Release desktop
+
m2d.release_desktop()
diff --git a/examples/03-Maxwell/Maxwell2D_Electrostatic.py b/examples/03-Maxwell/Maxwell2D_Electrostatic.py
index df21b3763f8..0f1f391dce5 100644
--- a/examples/03-Maxwell/Maxwell2D_Electrostatic.py
+++ b/examples/03-Maxwell/Maxwell2D_Electrostatic.py
@@ -1,45 +1,39 @@
-"""
-Maxwell 2D Electrostatic analysis
----------------------------------
-This example shows how you can use PyAEDT to create a Maxwell 2D electrostatic analysis.
-It shows how to create the geometry, load material properties from an Excel file and
-set up the mesh settings. Moreover, it focuses on post-processing operations, in particular how to
-plot field line traces, relevant for an electrostatic analysis.
-
-"""
-#################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 2D Electrostatic analysis
+
+# This example shows how you can use PyAEDT to create a Maxwell 2D electrostatic analysis.
+# It shows how to create the geometry, load material properties from an Excel file and
+# set up the mesh settings. Moreover, it focuses on post-processing operations, in particular how to
+# plot field line traces, relevant for an electrostatic analysis.
+
+# ## Perform required imports
+#
# Perform required imports.
import pyaedt
-#################################################################################
-# Initialize Maxwell 2D
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize Maxwell 2D
+#
# Initialize Maxwell 2D, providing the version, path to the project, and the design
# name and type.
desktopVersion = '2023.2'
-
sName = 'MySetupAuto'
sType = 'Electrostatic'
dName = 'Design1'
pName = pyaedt.generate_unique_project_name()
non_graphical = False
-#################################################################################
-# Download .xlsx file
-# ~~~~~~~~~~~~~~~~~~~
+# ## Download .xlsx file
+#
# Set local temporary folder to export the .xlsx file to.
file_name_xlsx = pyaedt.downloads.download_file("field_line_traces", "my_copper.xlsx")
-#################################################################################
-# Initialize dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize dictionaries
+#
# Initialize dictionaries that contain all the definitions for the design variables.
+# +
geom_params_circle = {
'circle_x0': '-10mm',
'circle_y0': '0mm',
@@ -56,10 +50,10 @@
'r_dx': '-1mm',
'r_dy': '-10mm'
}
+# -
-##################################################################################
-# Launch Maxwell 2D
-# ~~~~~~~~~~~~~~~~~
+# ## Launch Maxwell 2D
+#
# Launch Maxwell 2D and save the project.
M2D = pyaedt.Maxwell2d(projectname=pName,
@@ -70,18 +64,16 @@
non_graphical=non_graphical
)
-##################################################################################
-# Create object to access 2D modeler
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object to access 2D modeler
+#
# Create the object ``mod2D`` to access the 2D modeler easily.
mod2D = M2D.modeler
mod2D.delete()
mod2D.model_units = "mm"
-##################################################################################
-# Define variables from dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define variables from dictionaries
+#
# Define design variables from the created dictionaries.
for k, v in geom_params_circle.items():
@@ -89,19 +81,18 @@
for k, v in geom_params_rectangle.items():
M2D[k] = v
-##################################################################################
-# Read materials from .xslx file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Read materials from .xslx file
+#
# Read materials from .xslx file into and set into design.
mats = M2D.materials.import_materials_from_excel(file_name_xlsx)
-##################################################################################
-# Create design geometries
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create design geometries
+#
# Create rectangle and a circle and assign the material read from the .xlsx file.
# Create two new polylines and a region.
+# +
rect = mod2D.create_rectangle(position=['r_x0', 'r_y0', 'r_z0'],
dimension_list=['r_dx', 'r_dy', 0],
name='Ground', matname=mats[0])
@@ -119,25 +110,23 @@
poly2_id = mod2D.create_polyline(position_list=poly2_points, name='Poly2')
mod2D.split([poly1_id, poly2_id], 'YZ', sides='NegativeOnly')
mod2D.create_region([20, 100, 20, 100])
+# -
-##################################################################################
-# Define excitations
-# ~~~~~~~~~~~~~~~~~~
+# ## Define excitations
+#
# Assign voltage excitations to rectangle and circle.
M2D.assign_voltage(rect.id, amplitude=0, name='Ground')
M2D.assign_voltage(circle.id, amplitude=50e6, name='50kV')
-##################################################################################
-# Create initial mesh settings
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create initial mesh settings
+#
# Assign a surface mesh to the rectangle.
M2D.mesh.assign_surface_mesh_manual(names=['Ground'], surf_dev=0.001)
-##################################################################################
-# Create, validate and analyze the setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create, validate and analyze the setup
+#
# Create, update, validate and analyze the setup.
setup = M2D.create_setup(setupname=sName)
@@ -146,9 +135,8 @@
M2D.validate_simple()
M2D.analyze_setup(sName)
-##################################################################################
-# Evaluate the E Field tangential component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Evaluate the E Field tangential component
+#
# Evaluate the E Field tangential component along the given polylines.
# Add these operations to the Named Expression list in Field Calculator.
@@ -165,9 +153,8 @@
fields.CalcOp("Dot")
fields.AddNamedExpression("e_tan_poly2", "Fields")
-##################################################################################
-# Create Field Line Traces Plot
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create Field Line Traces Plot
+#
# Create Field Line Traces Plot specifying as seeding faces
# the ground, the electrode and the region
# and as ``In surface objects`` only the region.
@@ -176,9 +163,8 @@
"Region",
plot_name="LineTracesTest")
-###################################################################################
-# Update Field Line Traces Plot
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Update Field Line Traces Plot
+#
# Update field line traces plot.
# Update seeding points number, line style and line width.
@@ -187,9 +173,8 @@
plot.LineWidth = 3
plot.update()
-###################################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
M2D.save_project()
diff --git a/examples/03-Maxwell/Maxwell2D_NissanLeaf.py b/examples/03-Maxwell/Maxwell2D_NissanLeaf.py
index 96500ab1226..84c38f9698c 100644
--- a/examples/03-Maxwell/Maxwell2D_NissanLeaf.py
+++ b/examples/03-Maxwell/Maxwell2D_NissanLeaf.py
@@ -1,13 +1,10 @@
-"""
-Maxwell 2D: PM synchronous motor transient analysis
----------------------------------------------------
-This example shows how you can use PyAEDT to create a Maxwell 2D transient analysis for
-an interior permanent magnet electric motor.
-
-"""
-#################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 2D: PM synchronous motor transient analysis
+#
+# This example shows how you can use PyAEDT to create a Maxwell 2D transient analysis for
+# an interior permanent magnet electric motor.
+
+# ## Perform required imports
+#
# Perform required imports.
from math import sqrt as mysqrt
@@ -16,29 +13,24 @@
import os
import pyaedt
-#################################################################################
-# Initialize Maxwell 2D
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize Maxwell 2D
+#
# Initialize Maxwell 2D, providing the version, path to the project, and the design
# name and type.
desktopVersion = "2023.2"
-
sName = "MySetupAuto"
sType = "TransientXY"
-
pName = pyaedt.generate_unique_project_name()
dName = "Sinusoidal"
-#################################################################################
-# Initialize dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize dictionaries
+#
# Initialize dictionaries that contain all the definitions for the design
# variables and output variables.
-#################################################################################
-# Initialize definitions for stator, rotor, and shaft
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definitions for stator, rotor, and shaft
+#
# Initialize geometry parameter definitions for the stator, rotor, and shaft.
# The naming refers to RMxprt primitives.
@@ -54,9 +46,8 @@
"SlotType": "3"
}
-#################################################################################
-# Initialize definitions for stator windings
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definitions for stator windings
+#
# Initialize geometry parameter definitions for the stator windings. The naming
# refers to RMxprt primitives.
@@ -74,9 +65,8 @@
"Coil_Edge_Long": "15.37828521mm"
}
-#################################################################################
-# Initialize definitions for model setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definitions for model setup
+#
# Initialize geometry parameter definitions for the model setup.
mod_params = {
@@ -92,9 +82,8 @@
"Section_Angle": "360deg/SymmetryFactor"
}
-#################################################################################
-# Initialize definitions for operational machine
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definitions for operational machine
+#
# Initialize geometry parameter definitions for the operational machine. This
# identifies the operating point for the transient setup.
@@ -110,18 +99,16 @@
"Theta_i": "135deg"
}
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. ``"PYAEDT_NON_GRAPHICAL"`` is needed to
# generate documentation only.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-##########################################################
-# Launch Maxwell 2D
-# ~~~~~~~~~~~~~~~~~
+# ## Launch Maxwell 2D
+#
# Launch Maxwell 2D and save the project.
M2D = pyaedt.Maxwell2d(projectname=pName,
@@ -132,18 +119,16 @@
non_graphical=non_graphical
)
-##########################################################
-# Create object to access 2D modeler
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object to access 2D modeler
+#
# Create the object ``mod2D`` to access the 2D modeler easily.
mod2D = M2D.modeler
mod2D.delete()
mod2D.model_units = "mm"
-##########################################################
-# Define variables from dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define variables from dictionaries
+#
# Define design variables from the created dictionaries.
for k, v in geom_params.items():
@@ -155,17 +140,15 @@
for k, v in oper_params.items():
M2D[k] = v
-##########################################################
-# Define path for non-linear material properties
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define path for non-linear material properties
+#
# Define the path for non-linear material properties.
# Materials are stored in text files.
filename_lam, filename_PM = pyaedt.downloads.download_leaf()
-##########################################################
-# Create first material
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create first material
+#
# Create the material ``"Copper (Annealed)_65C"``.
mat_coils = M2D.materials.add_material("Copper (Annealed)_65C")
@@ -173,9 +156,8 @@
mat_coils.conductivity = "49288048.9198"
mat_coils.permeability = "1"
-##########################################################
-# Create second material
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create second material
+#
# Create the material ``"Arnold_Magnetics_N30UH_80C"``.
# The BH curve is read from a tabbed CSV file, and a list (``BH_List_PM``)
# is created. This list is passed to the ``mat_PM.permeability.value``
@@ -194,9 +176,8 @@
BH_List_PM.append([float(row[0]), float(row[1])])
mat_PM.permeability.value = BH_List_PM
-##########################################################
-# Create third material
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create third material
+#
# Create the laminated material ``30DH_20C_smooth``.
# This material has a BH curve and a core loss model,
# which is set to electrical steel.
@@ -219,13 +200,13 @@
BH_List_lam.append([float(row[0]), float(row[1])])
mat_lam.permeability.value = BH_List_lam
-##########################################################
-# Create geometry for stator
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for stator
+#
# Create the geometry for the stator. It is created via
# the RMxprt user-defined primitive. A list of lists is
# created with the proper UDP parameters.
+# +
udp_par_list_stator = [["DiaGap", "DiaGap"], ["DiaYoke", "DiaStatorYoke"], ["Length", "Stator_Lam_Length"],
["Skew", "StatorSkewAngle"], ["Slots", "SlotNumber"], ["SlotType", "SlotType"],
["Hs0", "1.2mm"], ["Hs01", "0mm"], ["Hs1", "0.4834227384999mm"],
@@ -240,10 +221,10 @@
stator_id = mod2D.create_udp(udp_dll_name="RMxprt/VentSlotCore.dll",
udp_parameters_list=udp_par_list_stator, upd_library='syslib',
name='my_stator') # name not taken
+# -
-##########################################################
-# Assign properties to stator
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign properties to stator
+#
# Assign properties to the stator. The following code assigns
# the material, name, color, and ``solve_inside`` properties.
@@ -252,10 +233,8 @@
stator_id.color = (0, 0, 255) # rgb
stator_id.solve_inside = True # to be reassigned: M2D.assign material puts False if not dielectric
-
-#####################################################################################
-# Create geometry for PMs
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for PMs
+#
# Create the geometry for the PMs (permanent magnets). In Maxwell 2D, you assign
# magnetization via the coordinate system. Because each PM needs to have a coordinate
# system in the face center, auxiliary functions are created. Here, you use the auxiliary
@@ -265,10 +244,8 @@
def find_elements(lst1, lst2):
return [lst1[i] for i in lst2]
-
-#####################################################################################
-# Find largest elements in list
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Find largest elements in list
+#
# Use the auxiliary function ``find_n_largest (input_len_list, n_largest_edges)``
# to find the ``n`` largest elements in the list ``input_len_list``.
@@ -282,15 +259,14 @@ def find_n_largest(input_len_list, n_largest_edges):
tmp[tmp.index(copied[-n])] = 0 # index can only get the first occurrence that solves the problem
return index_list
-
-#####################################################################################
-# Create coordinate system for PMs
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system for PMs
+#
# Create the coordinate system for the PMs. The inputs are the object name, coordinate
# system name, and inner or outer magnetization. Find the two longest edges of the magnets
# and get the midpoint of the outer edge. You must have this point to create the face
# coordinate systems in case of outer magnetization.
+# +
def create_cs_magnets(pm_id, cs_name, point_direction):
pm_face_id = mod2D.get_object_faces(pm_id.name)[0] # works with name only
pm_edges = mod2D.get_object_edges(pm_id.name) # gets the edges of the PM object
@@ -313,11 +289,10 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
axis="X", name=cs_name)
pm_id.part_coordinate_system = cs_name
mod2D.set_working_coordinate_system('Global')
+# -
-
-#####################################################################################
-# Create outer and inner PMs
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create outer and inner PMs
+#
# Create the outer and inner PMs and assign color to them.
IM1_points = [[56.70957112, 3.104886585, 0], [40.25081875, 16.67243502, 0], [38.59701538, 14.66621111, 0],
@@ -331,26 +306,23 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
matname="Arnold_Magnetics_N30UH_80C_new")
OPM1_id.color = (0, 128, 64)
-#####################################################################################
-# Create coordinate system for PMs in face center
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system for PMs in face center
+#
# Create the coordinate system for PMs in the face center.
create_cs_magnets(IPM1_id, 'CS_' + IPM1_id.name, 'outer')
create_cs_magnets(OPM1_id, 'CS_' + OPM1_id.name, 'outer')
-#####################################################################################
-# Duplicate and mirror PMs
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Duplicate and mirror PMs
+#
# Duplicate and mirror the PMs along with the local coordinate system.
mod2D.duplicate_and_mirror([IPM1_id, OPM1_id], position=[0, 0, 0],
vector=["cos((360deg/SymmetryFactor/2)+90deg)", "sin((360deg/SymmetryFactor/2)+90deg)", 0])
id_PMs = mod2D.get_objects_w_string("PM", case_sensitive=True)
-##########################################################
-# Create coils
-# ~~~~~~~~~~~~
+# ## Create coils
+#
# Create the coils.
coil_id = mod2D.create_rectangle(position=['DiaRotorLam/2+Airgap+Coil_SetBack', '-Coil_Edge_Short/2', 0],
@@ -362,9 +334,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
create_new_objects=True)
id_coils = mod2D.get_objects_w_string("Coil", case_sensitive=True)
-##########################################################
-# Create shaft and region
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create shaft and region
+#
# Create the shaft and region.
region_id = mod2D.create_circle(position=[0, 0, 0], radius='DiaOuter/2',
@@ -372,9 +343,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
shaft_id = mod2D.create_circle(position=[0, 0, 0], radius='DiaShaft/2',
num_sides='SegAngle', is_covered=True, name='Shaft')
-##########################################################
-# Create bands
-# ~~~~~~~~~~~~
+# ## Create bands
+#
# Create the inner band, band, and outer band.
bandIN_id = mod2D.create_circle(position=[0, 0, 0], radius='(DiaGap - (1.5 * Airgap))/2',
@@ -384,29 +354,27 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
bandOUT_id = mod2D.create_circle(position=[0, 0, 0], radius='(DiaGap - (0.5 * Airgap))/2',
num_sides='mapping_angle', is_covered=True, name='Outer_Band')
-##########################################################
-# Assign motion setup to object
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign motion setup to object
+#
# Assign a motion setup to a ``Band`` object named ``RotatingBand_mid``.
M2D.assign_rotate_motion(band_object='Band', coordinate_system="Global", axis="Z", positive_movement=True,
start_position="InitialPositionMD", angular_velocity="MachineRPM")
-##########################################################
-# Create list of vacuum objects
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create list of vacuum objects
+#
# Create a list of vacuum objects and assign color.
vacuum_obj_id = [shaft_id, region_id, bandIN_id, bandMID_id, bandOUT_id] # put shaft first
for item in vacuum_obj_id:
item.color = (128, 255, 255)
-##########################################################
-# Create rotor
-# ~~~~~~~~~~~~
+# ## Create rotor
+#
# Create the rotor. Holes are specific to the lamination.
# Allocated PMs are created.
+# +
rotor_id = mod2D.create_circle(position=[0, 0, 0], radius='DiaRotorLam/2',
num_sides=0, name="Rotor", matname="30DH_20C_smooth")
rotor_id.color = (0, 128, 255)
@@ -434,13 +402,14 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
id_holes = mod2D.get_objects_w_string("slot_", case_sensitive=True)
M2D.modeler.subtract(rotor_id, id_holes, keep_originals=True)
+# -
-##########################################################
-# Create section of machine
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create section of machine
+#
# Create a section of the machine. This allows you to take
# advantage of symmetries.
+# +
object_list = [stator_id, rotor_id] + vacuum_obj_id
mod2D.create_coordinate_system(origin=[0, 0, 0],
reference_cs="Global",
@@ -453,10 +422,10 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
mod2D.split(object_list, "ZX", sides="NegativeOnly")
mod2D.set_working_coordinate_system("Global")
mod2D.split(object_list, "ZX", sides="PositiveOnly")
+# -
-##########################################################
-# Create boundary conditions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create boundary conditions
+#
# Create independent and dependent boundary conditions.
# Edges for assignment are picked by position.
# The points for edge picking are in the airgap.
@@ -472,9 +441,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
same_as_master=False,
bound_name="Matching")
-##########################################################
-# Assign vector potential
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign vector potential
+#
# Assign a vector potential of ``0`` to the second position.
pos_2 = "(DiaOuter/2)"
@@ -483,18 +451,16 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
obj_name='Region')
M2D.assign_vector_potential(id_bc_az, vectorvalue=0, bound_name="VectorPotentialZero")
-##########################################################
-# Create excitations
-# ~~~~~~~~~~~~~~~~~~
+# ## Create excitations
+#
# Create excitations, defining phase currents for the windings.
PhA_current = "IPeak * cos(2*pi*ElectricFrequency*time+Theta_i)"
PhB_current = "IPeak * cos(2*pi * ElectricFrequency*time - 120deg+Theta_i)"
PhC_current = "IPeak * cos(2*pi * ElectricFrequency*time - 240deg+Theta_i)"
-##########################################################
-# Define windings in phase A
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define windings in phase A
+#
# Define windings in phase A.
M2D.assign_coil(input_object=["Coil"], conductor_number=6, polarity="Positive", name="CT_Ph1_P2_C1_Go")
@@ -503,9 +469,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
current_value=PhA_current, parallel_branches=1, name="Phase_A")
M2D.add_winding_coils(windingname="Phase_A", coil_names=["CT_Ph1_P2_C1_Go", "CT_Ph1_P2_C1_Ret"])
-##########################################################
-# Define windings in phase B
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define windings in phase B
+#
# Define windings in phase B.
M2D.assign_coil(input_object="Coil_3", conductor_number=6, polarity="Positive", name="CT_Ph3_P1_C2_Go")
@@ -515,9 +480,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
name="Phase_B")
M2D.add_winding_coils(windingname="Phase_B", coil_names=["CT_Ph3_P1_C2_Go", "CT_Ph3_P1_C1_Go"])
-##########################################################
-# Define windings in phase C
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define windings in phase C
+#
# Define windings in phase C.
M2D.assign_coil(input_object="Coil_1", conductor_number=6, polarity="Negative", name="CT_Ph2_P2_C2_Ret")
@@ -527,65 +491,58 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
name="Phase_C")
M2D.add_winding_coils(windingname="Phase_C", coil_names=["CT_Ph2_P2_C2_Ret", "CT_Ph2_P2_C1_Ret"])
-##########################################################
-# Assign total current on PMs
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign total current on PMs
+#
# Assign a total current of ``0`` on the PMs.
PM_list = id_PMs
for item in PM_list:
M2D.assign_current(item, amplitude=0, solid=True, name=item + "_I0")
-##########################################################
-# Create mesh operations
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create mesh operations
+#
# Create the mesh operations.
M2D.mesh.assign_length_mesh(id_coils, isinside=True, maxlength=3, maxel=None, meshop_name="coils")
M2D.mesh.assign_length_mesh(stator_id, isinside=True, maxlength=3, maxel=None, meshop_name="stator")
M2D.mesh.assign_length_mesh(rotor_id, isinside=True, maxlength=3, maxel=None, meshop_name="rotor")
-##########################################################
-# Turn on eddy effects
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Turn on eddy effects
+#
# Turn on eddy effects.
# M2D.eddy_effects_on(eddy_effects_list,activate_eddy_effects=True, activate_displacement_current=False)
-##########################################################
-# Turn on core loss
-# ~~~~~~~~~~~~~~~~~
+# ## Turn on core loss
+#
# Turn on core loss.
core_loss_list = ['Rotor', 'Stator']
M2D.set_core_losses(core_loss_list, value=True)
-##########################################################
-# Compute transient inductance
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Compute transient inductance
+#
# Compute the transient inductance.
M2D.change_inductance_computation(compute_transient_inductance=True, incremental_matrix=False)
-##########################################################
-# Set model depth
-# ~~~~~~~~~~~~~~~
+# ## Set model depth
+#
# Set the model depth.
M2D.model_depth = "Magnetic_Axial_Length"
-##########################################################
-# Set symmetry factor
-# ~~~~~~~~~~~~~~~~~~~
+# ## Set symmetry factor
+#
# Set the symmetry factor.
M2D.change_symmetry_multiplier("SymmetryFactor")
-##########################################################
-# Create setup and validate
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and validate
+#
# Create the setup and validate it.
+# +
setup = M2D.create_setup(setupname=sName)
setup.props["StopTime"] = "StopTime"
setup.props["TimeStep"] = "TimeStep"
@@ -598,10 +555,10 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
model = M2D.plot(show=False)
model.plot(os.path.join(M2D.working_directory, "Image.jpg"))
+# -
-#################################################################################
-# Initialize definitions for output variables
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definitions for output variables
+#
# Initialize the definitions for the output variables.
# These will be used later to generate reports.
@@ -646,25 +603,23 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
"U_q": "-2/3*(U_A*sin0 + U_B*sin1 + U_C*sin2)"
}
-##########################################################
-# Create output variables for postprocessing
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create output variables for postprocessing
+#
# Create output variables for postprocessing.
for k, v in output_vars.items():
M2D.create_output_variable(k, v)
-#################################################################################
-# Initialize definition for postprocessing plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize definition for postprocessing plots
+#
# Initialize the definition for postprocessing plots.
post_params = {
"Moving1.Torque": "TorquePlots"
}
-#################################################################################
-# Initialize definition for postprocessing multiplots
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Initialize definition for postprocessing multiplots
+#
# Initialize the definition for postprocessing multiplots.
post_params_multiplot = { # reports
@@ -686,9 +641,8 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
("SolidLoss", "SolidLoss(IPM1)", "SolidLoss(IPM1_1)", "SolidLoss(OPM1)", "SolidLoss(OPM1_1)"): "SolidLoss"
}
-##########################################################
-# Create report
-# ~~~~~~~~~~~~~
+# ## Create report
+#
# Create a report.
for k, v in post_params.items():
@@ -697,29 +651,27 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
report_category=None, plot_type="Rectangular Plot", context=None, subdesign_id=None,
polyline_points=1001, plotname=v)
-##########################################################
-# Create multiplot report
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create multiplot report
+#
# Create a multiplot report.
+# +
# for k, v in post_params_multiplot.items():
# M2D.post.create_report(expressions=list(k), setup_sweep_name="", domain="Sweep", variations=None,
# primary_sweep_variable="Time", secondary_sweep_variable=None,
# report_category=None, plot_type="Rectangular Plot", context=None, subdesign_id=None,
# polyline_points=1001, plotname=v)
+# -
-
-##########################################################
-# Analyze and save project
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Analyze and save project
+#
# Analyze and save the project.
M2D.save_project()
M2D.analyze_setup(sName, use_auto_settings=False)
-##########################################################
-# Create flux lines plot on region
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create flux lines plot on region
+#
# Create a flux lines plot on a region. The ``object_list`` is
# formerly created when the section is applied.
@@ -730,16 +682,14 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
"Time": M2D.variable_manager.variables["StopTime"].evaluated_value},
plot_name="Flux_Lines")
-##########################################################
-# Export a field plot to an image file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export a field plot to an image file
+#
# Export the flux lines plot to an image file using Python PyVista.
M2D.post.plot_field_from_fieldplot(plot1.name, show=False)
-###############################################
-# Get solution data
-# ~~~~~~~~~~~~~~~~~
+# ## Get solution data
+#
# Get a simulation result from a solved setup and cast it in a ``SolutionData`` object.
# Plot the desired expression by using Matplotlib plot().
@@ -747,26 +697,23 @@ def create_cs_magnets(pm_id, cs_name, point_direction):
primary_sweep_variable="Time")
#solutions.plot()
-###############################################
-# Retrieve the data magnitude of an expression
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Retrieve the data magnitude of an expression
+#
# List of shaft torque points and compute average.
mag = solutions.data_magnitude()
avg = sum(mag) / len(mag)
-###############################################
-# Export a report to a file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Export a report to a file
+#
# Export a 2D Plot data to a .csv file.
M2D.post.export_report_to_file(output_dir=M2D.toolkit_directory,
plot_name="TorquePlots",
extension=".csv")
-###############################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# Close AEDT.
M2D.release_desktop()
diff --git a/examples/03-Maxwell/Maxwell2D_Transient.py b/examples/03-Maxwell/Maxwell2D_Transient.py
index c65c9b89ab8..520b725d6c1 100644
--- a/examples/03-Maxwell/Maxwell2D_Transient.py
+++ b/examples/03-Maxwell/Maxwell2D_Transient.py
@@ -1,81 +1,71 @@
-"""
-Maxwell 2D: transient winding analysis
---------------------------------------
-This example shows how you can use PyAEDT to create a project in Maxwell 2D
-and run a transient simulation. It runs only on Windows using CPython.
-
-The following libraries are required for the advanced postprocessing features
-used in this example:
-
-- `Matplotlib `_
-- `Numpty `_
-- `PyVista `_
-
-Install these libraries with:
-
-.. code::
-
- pip install numpy pyvista matplotlib
-
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 2D: transient winding analysis
+#
+# This example shows how you can use PyAEDT to create a project in Maxwell 2D
+# and run a transient simulation. It runs only on Windows using CPython.
+#
+# The following libraries are required for the advanced postprocessing features
+# used in this example:
+#
+# - `Matplotlib `_
+# - `Numpty `_
+# - `PyVista `_
+#
+# Install these libraries with:
+#
+# ```console
+# pip install numpy pyvista matplotlib
+# ```
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Insert Maxwell 2D design and save project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert Maxwell 2D design and save project
+#
# Insert a Maxwell 2D design and save the project.
maxwell_2d = pyaedt.Maxwell2d(solution_type="TransientXY", specified_version="2023.2", non_graphical=non_graphical,
new_desktop_session=True, projectname=pyaedt.generate_unique_project_name())
-###############################################################################
-# Create rectangle and duplicate it
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create rectangle and duplicate it
+#
# Create a rectangle and duplicate it.
rect1 = maxwell_2d.modeler.create_rectangle([0, 0, 0], [10, 20], name="winding", matname="copper")
added = rect1.duplicate_along_line([14, 0, 0])
rect2 = maxwell_2d.modeler[added[0]]
-###############################################################################
-# Create air region
-# ~~~~~~~~~~~~~~~~~
+# ## Create air region
+#
# Create an air region.
region = maxwell_2d.modeler.create_region([100, 100, 100, 100, 100, 100])
-###############################################################################
-# Assign windings and balloon
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign windings and balloon
+#
# Assigns windings to the sheets and a balloon to the air region.
maxwell_2d.assign_winding([rect1.name, rect2.name], name="PHA")
maxwell_2d.assign_balloon(region.edges)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
maxwell_2d.plot(show=False, export_path=os.path.join(maxwell_2d.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create the transient setup.
setup = maxwell_2d.create_setup()
@@ -86,27 +76,25 @@
setup.props["Steps From"] = "0s"
setup.props["Steps To"] = "0.002s"
-###############################################################################
-# Create rectangular plot
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create rectangular plot
+#
# Create a rectangular plot.
maxwell_2d.post.create_report(
"InputCurrent(PHA)", domain="Time", primary_sweep_variable="Time", plotname="Winding Plot 1"
)
-###############################################################################
-# Solve model
-# ~~~~~~~~~~~
+# ## Solve model
+#
# Solve the model.
maxwell_2d.analyze(use_auto_settings=False)
-###############################################################################
-# Create output and plot using PyVista
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create output and plot using PyVista
+#
# Create the output and plot it using PyVista.
+# +
cutlist = ["Global:XY"]
face_lists = rect1.faces
face_lists += rect2.faces
@@ -129,21 +117,21 @@
animatedGif.roll_angle = 0
animatedGif.elevation_angle = 0
animatedGif.azimuth_angle = 0
+
# Set off_screen to False to visualize the animation.
# animatedGif.off_screen = False
animatedGif.animate()
+# -
-###############################################################################
-# Generate plot outside of AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate plot outside of AEDT
+#
# Generate the same plot outside AEDT.
solutions = maxwell_2d.post.get_solution_data("InputCurrent(PHA)", primary_sweep_variable="Time")
solutions.plot()
-###############################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# Close AEDT.
maxwell_2d.release_desktop()
diff --git a/examples/03-Maxwell/Maxwell3DTeam7.py b/examples/03-Maxwell/Maxwell3DTeam7.py
index 8ffd1d989b6..a90e183bb2d 100644
--- a/examples/03-Maxwell/Maxwell3DTeam7.py
+++ b/examples/03-Maxwell/Maxwell3DTeam7.py
@@ -4,9 +4,8 @@
This example uses PyAEDT to set up the TEAM 7 problem for an asymmetric
conductor with a hole and solve it using the Maxwell 3D Eddy Current solver.
"""
-###########################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports.
from pyaedt import Maxwell3d
@@ -15,20 +14,19 @@
import csv
import os
-###########################################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###########################################################################################
-# Launch AEDT and Maxwell 3D
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and Maxwell 3D
+#
# Launch AEDT and Maxwell 3D. The following code sets up the project and design names, the solver, and
# the version. It also creates an instance of the ``Maxwell3d`` class named ``M3D``.
+# +
Project_Name = "COMPUMAG"
Design_Name = "TEAM 7 Asymmetric Conductor"
Solver = "EddyCurrent"
@@ -45,15 +43,16 @@
M3D.modeler.model_units = "mm"
modeler = M3D.modeler
Plot = M3D.odesign.GetModule("ReportSetup")
+# -
-###########################################################################################
-# Add Maxwell 3D setup
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Add Maxwell 3D setup
+#
# Add a Maxwell 3D setup with frequency points at DC, 50 Hz, and 200Hz.
# Otherwise, the default PyAEDT setup values are used. To approximate a DC field in the
# Eddy Current solver, use a low frequency value. Second-order shape functions improve
# the smoothness of the induced currents in the plate.
+# +
dc_freq = 0.1
stop_freq = 50
@@ -63,10 +62,10 @@
Setup.add_eddy_current_sweep("LinearStep", dc_freq, stop_freq, stop_freq - dc_freq, clear=True)
Setup.props["UseHighOrderShapeFunc"] = True
Setup.props["PercentError"] = 0.4
+# -
-###########################################################################################
-# Define coil dimensions
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Define coil dimensions
+#
# Define coil dimensions as shown on the TEAM7 drawing of the coil.
coil_external = 150 + 25 + 25
@@ -85,29 +84,27 @@
dim3 = dim2 + np.sqrt(((coil_r1 + (coil_r2 - coil_r1) / 2) ** 2) / 2)
# Use coordinates to draw a polyline along which to sweep the coil cross sections.
+
P1 = [dim1, -dim2, 0]
P2 = [dim1, dim2, 0]
P3 = [dim3, dim3, 0]
P4 = [dim2, dim1, 0]
-###########################################################################################
-# Create coordinate system for positioning coil
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system for positioning coil
+#
# Create a coordinate system for positioning the coil.
M3D.modeler.create_coordinate_system(origin=coil_centre, mode="view", view="XY", name="Coil_CS")
-###########################################################################################
-# Create polyline
-# ~~~~~~~~~~~~~~~
+# ## Create polyline
+#
# Create a polyline. One quarter of the coil is modeled by sweeping a 2D sheet along a polyline.
test = M3D.modeler.create_polyline(position_list=[P1, P2, P3, P4], segment_type=["Line", "Arc"], name="Coil")
test.set_crosssection_properties(type="Rectangle", width=coil_thk, height=coil_height)
-###########################################################################################
-# Duplicate and unite polyline to create full coil
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Duplicate and unite polyline to create full coil
+#
# Duplicate and unit the polyline to create a full coil.
M3D.modeler.duplicate_around_axis(
@@ -117,26 +114,24 @@
M3D.modeler.unite("Coil,Coil_3")
M3D.modeler.fit_all()
-###########################################################################################
-# Assign material and if solution is allowed inside coil
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign material and if solution is allowed inside coil
+#
# Assign the material ``Cooper`` from the Maxwell internal library to the coil and
# allow a solution inside the coil.
M3D.assign_material("Coil", "Copper")
M3D.solve_inside("Coil")
-###########################################################################################
-# Create terminal
-# ~~~~~~~~~~~~~~~
+# ## Create terminal
+#
# Create a terminal for the coil from a cross section that is split and one half deleted.
M3D.modeler.section("Coil", "YZ")
M3D.modeler.separate_bodies("Coil_Section1")
M3D.modeler.delete("Coil_Section1_Separate1")
-# Add variable for coil excitation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Add variable for coil excitation
+#
# Add a design variable for coil excitation. The NB units here are AmpereTurns.
Coil_Excitation = 2742
@@ -144,17 +139,15 @@
M3D.assign_current("Coil_Section1", amplitude="Coil_Excitation", solid=False)
M3D.modeler.set_working_coordinate_system("Global")
-###########################################################################################
-# Add a material
-# ~~~~~~~~~~~~~~
+# ## Add a material
+#
# Add a material named ``team3_aluminium``.
mat = M3D.materials.add_material("team7_aluminium")
mat.conductivity = 3.526e7
-###########################################################################################
-# Model aluminium plate with a hole
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Model aluminium plate with a hole
+#
# Model the aluminium plate with a hole by subtracting two rectangular cuboids.
plate = M3D.modeler.create_box(position=[0, 0, 0], dimensions_list=[294, 294, 19], name="Plate",
@@ -163,16 +156,14 @@
hole = M3D.modeler.create_box(position=[18, 18, 0], dimensions_list=[108, 108, 19], name="Hole")
M3D.modeler.subtract("Plate", ["Hole"], keep_originals=False)
-###########################################################################################
-# Draw a background region
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw a background region
+#
# Draw a background region that uses the default properties for an air region.
M3D.modeler.create_air_region(x_pos=100, y_pos=100, z_pos=100, x_neg=100, y_neg=100, z_neg=100)
-################################################################################
-# Adjust eddy effects for plate and coil
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Adjust eddy effects for plate and coil
+#
# Adjust the eddy effects for the plate and coil by turning off displacement currents
# for all parts. The setting for eddy effect is ignored for the stranded conductor type
# used in the coil.
@@ -182,9 +173,8 @@
activate_eddy_effects=False,
activate_displacement_current=False)
-################################################################################
-# Create expression for Z component of B in Gauss
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create expression for Z component of B in Gauss
+#
# Create an expression for the Z component of B in Gauss using the fields calculator.
Fields = M3D.odesign.GetModule("FieldsReporter")
@@ -197,12 +187,12 @@
Fields.CalcOp("Smooth")
Fields.AddNamedExpression("Bz", "Fields")
-################################################################################
-# Draw two lines along which to plot Bz
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw two lines along which to plot Bz
+#
# Draw two lines along which to plot Bz. The following code also adds a small cylinder
# to refine the mesh locally around each line.
+# +
lines = ["Line_A1_B1", "Line_A2_B2"]
mesh_diameter = "2mm"
@@ -215,19 +205,19 @@
polyline2 = modeler.create_polyline(position_list=line_points_2, name=lines[1])
polyline2_mesh = modeler.create_polyline(position_list=line_points_2, name=lines[1] + "mesh")
polyline2_mesh.set_crosssection_properties(type="Circle", width=mesh_diameter)
+# -
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
M3D.plot(show=False, export_path=os.path.join(M3D.working_directory, "Image.jpg"), plot_air_objects=False)
-################################################################################
# Published measurement results are included with this script via the list below.
# Test results are used to create text files for import into a rectangular plot
# and to overlay simulation results.
+# +
project_dir = M3D.working_directory
dataset = [
"Bz A1_B1 000 0",
@@ -344,12 +334,14 @@
],
[-1.35, -0.71, -0.81, -0.67, 0.15, 1.39, 2.67, 3.00, 4.01, 3.80, 4.00, 3.02, 2.20, 2.78, 1.58, 1.37, 0.93],
]
+# -
# Dataset details are used to encode test parameters in the text files.
# For example, ``Bz A1_B1 050 0`` is the Z component of flux density ``B``
# along line ``A1_B1`` at 50 Hz and 0 deg. These text files are created
# and saved in the default project directory.
+# +
print("project_dir", project_dir)
dataset_range = range(int(0), len(dataset), int(1))
line_length_range = range(int(0), len(line_length), int(1))
@@ -364,9 +356,10 @@
writer = csv.writer(f, delimiter=",")
writer.writerow(header)
writer.writerows(ziplist)
-
-# Create rectangular plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# -
+
+# ## Create rectangular plots
+#
# Create rectangular plots, using text file encoding to control their formatting. Create
# the DC plot separately because it needs a different frequency and phase than the other plots.
@@ -404,8 +397,8 @@
expressions=dataset[item][0:2],
)
-# Import test data into correct plot and overlay with simulation results
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import test data into correct plot and overlay with simulation results
+#
# Import test data into the correct plot and overlay it with the simulation results.
if item == 0:
@@ -414,9 +407,8 @@
Plot.ImportIntoReport(plotname, project_dir + "\\" + str(dataset[item - 1]) + ".csv")
Plot.ImportIntoReport(plotname, project_dir + "\\" + str(dataset[item]) + ".csv")
-###################################################################################################
-# Create plots of induced current and flux density on surface of plate
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create plots of induced current and flux density on surface of plate
+#
# Create two plots of the induced current (``Mag_J``) and the flux density (``Mag_B``) on the
# surface of the plate.
@@ -425,17 +417,15 @@
M3D.post.create_fieldplot_surface(surflist, "Mag_J", intrinsincDict=intrinsic_dict, plot_name="Mag_J")
M3D.post.create_fieldplot_surface(surflist, "Mag_B", intrinsincDict=intrinsic_dict, plot_name="Mag_B")
-###################################################################################################
-# Save project and solve
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and solve
+#
# Save the project and solve it.
M3D.save_project()
M3D.analyze()
-####################################################################################################
-# Release AEDT from PyAEDT scripting
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Release AEDT from PyAEDT scripting
+#
# Release AEDT from PyAEDT scripting. If you wanted to leave AEDT and the project open
# after running the above script, in the following command, you would set ``(False, False)``.
diff --git a/examples/03-Maxwell/Maxwell3D_Choke.py b/examples/03-Maxwell/Maxwell3D_Choke.py
index d21690b8d1e..8a4b14ea1aa 100644
--- a/examples/03-Maxwell/Maxwell3D_Choke.py
+++ b/examples/03-Maxwell/Maxwell3D_Choke.py
@@ -1,29 +1,25 @@
-"""
-Maxwell 3D: choke setup
------------------------
-This example shows how you can use PyAEDT to create a choke setup in Maxwell 3D.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 3D: choke setup
+#
+# This example shows how you can use PyAEDT to create a choke setup in Maxwell 3D.
+
+# ## Perform required imports
+#
# Perform required imports.
import json
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can define ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
version = "2023.2"
-###############################################################################
-# Launch Maxwell3D
-# ~~~~~~~~~~~~~~~~
+# ## Launch Maxwell3D
+#
# Launch Maxwell 3D 2023 R2 in graphical mode.
m3d = pyaedt.Maxwell3d(projectname=pyaedt.generate_unique_project_name(),
@@ -33,9 +29,8 @@
new_desktop_session=True
)
-###############################################################################
-# Rules and information of use
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Rules and information of use
+#
# The dictionary values containing the different parameters of the core and
# the windings that compose the choke. You must not change the main structure of
# the dictionary. The dictionary has many primary keys, including
@@ -98,20 +93,20 @@
"Inner Winding": {"Turns": 10, "Coil Pit(deg)": 4, "Occupation(%)": 0},
}
-###############################################################################
-# Convert dictionary to JSON file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Convert dictionary to JSON file
+#
# Covert a dictionary to a JSON file. PyAEDT methods ask for the path of the
# JSON file as an argument. You can convert a dictionary to a JSON file.
+# +
json_path = os.path.join(m3d.working_directory, "choke_example.json")
with open(json_path, "w") as outfile:
json.dump(values, outfile)
+# -
-###############################################################################
-# Verify parameters of JSON file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Verify parameters of JSON file
+#
# Verify parameters of the JSON file. The ``check_choke_values`` method takes
# the JSON file path as an argument and does the following:
#
@@ -121,9 +116,8 @@
dictionary_values = m3d.modeler.check_choke_values(json_path, create_another_file=False)
print(dictionary_values)
-###############################################################################
-# Create choke
-# ~~~~~~~~~~~~
+# ## Create choke
+#
# Create the choke. The ``create_choke`` method takes the JSON file path as an
# argument.
@@ -134,9 +128,8 @@
second_winding_list = list_object[3]
third_winding_list = list_object[4]
-###############################################################################
-# Assign excitations
-# ~~~~~~~~~~~~~~~~~~
+# ## Assign excitations
+#
# Assign excitations.
first_winding_faces = m3d.modeler.get_object_faces(first_winding_list[0].name)
@@ -149,16 +142,14 @@
m3d.assign_current([third_winding_faces[-1]], amplitude=1000, phase="240deg", swap_direction=False, name="phase_3_in")
m3d.assign_current([third_winding_faces[-2]], amplitude=1000, phase="240deg", swap_direction=True, name="phase_3_out")
-###############################################################################
-# Assign matrix
-# ~~~~~~~~~~~~~
+# ## Assign matrix
+#
# Assign the matrix.
m3d.assign_matrix(["phase_1_in", "phase_2_in", "phase_3_in"], matrix_name="current_matrix")
-###############################################################################
-# Create mesh operation
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create mesh operation
+#
# Create the mesh operation.
mesh = m3d.mesh
@@ -175,16 +166,14 @@
meshop_name="surface_approx",
)
-###############################################################################
-# Create boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Create boundaries
+#
# Create the boundaries. A region with openings is needed to run the analysis.
region = m3d.modeler.create_air_region(x_pos=100, y_pos=100, z_pos=100, x_neg=100, y_neg=100, z_neg=0)
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup with a sweep to run the simulation. Depending on your machine's
# computing power, the simulation can take some time to run.
@@ -196,18 +185,16 @@
setup.props["HasSweepSetup"] = True
setup.add_eddy_current_sweep(range_type="LinearCount", start=100, end=1000, count=12, units="kHz", clear=True)
-###############################################################################
-# Save project
-# ~~~~~~~~~~~~
+# ## Save project
+#
# Save the project.
m3d.save_project()
m3d.modeler.fit_all()
m3d.plot(show=False, export_path=os.path.join(m3d.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.release_desktop` method.
# All methods provide for saving the project before closing.
diff --git a/examples/03-Maxwell/Maxwell3D_Segmentation.py b/examples/03-Maxwell/Maxwell3D_Segmentation.py
index e012e6b4e18..7fa569492a8 100644
--- a/examples/03-Maxwell/Maxwell3D_Segmentation.py
+++ b/examples/03-Maxwell/Maxwell3D_Segmentation.py
@@ -4,33 +4,30 @@
This example shows how you can use PyAEDT to segment magnets of an electric motor.
The method is valid and usable for any object the user would like to segment.
"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports.
from pyaedt import downloads
from pyaedt import generate_unique_folder_name
from pyaedt import Maxwell3d
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-#################################################################################
-# Download .aedt file example
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download .aedt file example
+#
# Set local temporary folder to export the .aedt file to.
+
temp_folder = generate_unique_folder_name()
aedt_file = downloads.download_file("object_segmentation", "Motor3D_obj_segments.aedt", temp_folder)
-##################################################################################
-# Launch Maxwell 3D
-# ~~~~~~~~~~~~~~~~~
+# ## Launch Maxwell 3D
+#
# Launch Maxwell 3D.
m3d = Maxwell3d(projectname=aedt_file,
@@ -38,16 +35,14 @@
new_desktop_session=True,
non_graphical=non_graphical)
-##################################################################################
-# Create object to access 3D modeler
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object to access 3D modeler
+#
# Create the object ``mod3D`` to access the 3D modeler easily.
modeler = m3d.modeler
-##################################################################################
-# Segment first magnet by specifying the number of segments
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Segment first magnet by specifying the number of segments
+#
# Select first magnet to segment by specifying the number of segments.
# The method accepts in input either the list of magnets names to segment or
# magnets ids or the magnet object :class:`pyaedt.modeler.cad.object3d.Object3d`.
@@ -59,9 +54,8 @@
object_name = "PM_I1"
sheets_1 = modeler.objects_segmentation(object_name, segments_number=segments_number, apply_mesh_sheets=True)
-##################################################################################
-# Segment second magnet by specifying the number of segments
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Segment second magnet by specifying the number of segments
+#
# Select second magnet to segment by specifying the number of segments.
# In this specific case we give as input the id of the magnet.
@@ -70,9 +64,8 @@
magnet_id = [obj.id for obj in modeler.object_list if obj.name == object_name][0]
sheets_2 = modeler.objects_segmentation(magnet_id, segments_number=segments_number, apply_mesh_sheets=True)
-##################################################################################
-# Segment third magnet by specifying the segmentation thickness
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Segment third magnet by specifying the segmentation thickness
+#
# Select third magnet to segment by specifying the segmentation thickness.
# In this specific case we give as input the magnet object of type :class:`pyaedt.modeler.cad.object3d.Object3d`.
@@ -81,9 +74,8 @@
magnet = [obj for obj in modeler.object_list if obj.name == object_name][0]
sheets_3 = modeler.objects_segmentation(magnet, segmentation_thickness=segmentation_thickness, apply_mesh_sheets=True)
-##################################################################################
-# Segment fourth magnet by specifying the number of segments
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Segment fourth magnet by specifying the number of segments
+#
# Select fourth magnet to segment by specifying the number of segments.
# In this specific case we give as input the name of the magnet and we disable the mesh sheets.
@@ -91,9 +83,8 @@
segments_number = 10
sheets_4 = modeler.objects_segmentation(object_name, segments_number=segments_number)
-###################################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
m3d.save_project()
diff --git a/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py b/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py
index d93025e6f78..919f42bb8e7 100644
--- a/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py
+++ b/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py
@@ -4,29 +4,27 @@
This example uses PyAEDT to set up the TEAM 3 bath plate problem and
solve it using the Maxwell 3D Eddy Current solver.
"""
-##################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-##################################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-##################################################################################
-# Launch AEDT and Maxwell 3D
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and Maxwell 3D
+#
# Launch AEDT and Maxwell 3D after first setting up the project and design names,
# the solver, and the version. The following code also creates an instance of the
# ``Maxwell3d`` class named ``M3D``.
+# +
project_name = "COMPUMAG"
design_name = "TEAM 3 Bath Plate"
Solver = "EddyCurrent"
@@ -42,34 +40,31 @@
)
uom = m3d.modeler.model_units = "mm"
modeler = m3d.modeler
+# -
-###############################################################################
-# Add variable
-# ~~~~~~~~~~~~
+# ## Add variable
+#
# Add a design variable named ``Coil_Position`` that you use later to adjust the
# position of the coil.
Coil_Position = -20
m3d["Coil_Position"] = str(Coil_Position) + uom # Creates a design variable in Maxwell
-################################################################################
-# Add material
-# ~~~~~~~~~~~~
+# ## Add material
+#
# Add a material named ``team3_aluminium`` for the ladder plate.
mat = m3d.materials.add_material("team3_aluminium")
mat.conductivity = 32780000
-###############################################################################
-# Draw background region
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw background region
+#
# Draw a background region that uses the default properties for an air region.
m3d.modeler.create_air_region(x_pos=100, y_pos=100, z_pos=100, x_neg=100, y_neg=100, z_neg=100)
-################################################################################
-# Draw ladder plate and assign material
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw ladder plate and assign material
+#
# Draw a ladder plate and assign it the newly created material ``team3_aluminium``.
m3d.modeler.create_box(position=[-30, -55, 0], dimensions_list=[60, 110, -6.35], name="LadderPlate",
@@ -78,16 +73,14 @@
m3d.modeler.create_box(position=[-20, 5, 0], dimensions_list=[40, 30, -6.35], name="CutoutTool2")
m3d.modeler.subtract("LadderPlate", ["CutoutTool1", "CutoutTool2"], keep_originals=False)
-################################################################################
-# Add mesh refinement to ladder plate
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Add mesh refinement to ladder plate
+#
# Add a mesh refinement to the ladder plate.
m3d.mesh.assign_length_mesh("LadderPlate", maxlength=3, maxel=None, meshop_name="Ladder_Mesh")
-################################################################################
-# Draw search coil and assign excitation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw search coil and assign excitation
+#
# Draw a search coil and assign it a ``stranded`` current excitation.
# The stranded type forces the current density to be constant in the coil.
@@ -103,9 +96,8 @@
m3d.modeler.delete("SearchCoil_Section1_Separate1")
m3d.assign_current(object_list=["SearchCoil_Section1"], amplitude=1260, solid=False, name="SearchCoil_Excitation")
-################################################################################
-# Draw a line for plotting Bz
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Draw a line for plotting Bz
+#
# Draw a line for plotting Bz later. Bz is the Z component of the flux
# density. The following code also adds a small diameter cylinder to refine the
# mesh locally around the line.
@@ -115,16 +107,14 @@
P2 = modeler.create_polyline(position_list=Line_Points, name="Line_AB_MeshRefinement")
P2.set_crosssection_properties(type="Circle", width="0.5mm")
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
m3d.plot(show=False, export_path=os.path.join(m3d.working_directory, "Image.jpg"), plot_air_objects=False)
-###############################################################################
-# Add Maxwell 3D setup
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Add Maxwell 3D setup
+#
# Add a Maxwell 3D setup with frequency points at 50 Hz and 200 Hz.
Setup = m3d.create_setup(setupname="Setup1")
@@ -132,18 +122,16 @@
Setup.props["HasSweepSetup"] = True
Setup.add_eddy_current_sweep(range_type="LinearStep", start=50, end=200, count=150, clear=True)
-################################################################################
-# Adjust eddy effects
-# ~~~~~~~~~~~~~~~~~~~
+# ## Adjust eddy effects
+#
# Adjust eddy effects for the ladder plate and the search coil. The setting for
# eddy effect is ignored for the stranded conductor type used in the search coil.
m3d.eddy_effects_on(["LadderPlate"], activate_eddy_effects=True, activate_displacement_current=True)
m3d.eddy_effects_on(["SearchCoil"], activate_eddy_effects=False, activate_displacement_current=True)
-################################################################################
-# Add linear parametric sweep
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Add linear parametric sweep
+#
# Add a linear parametric sweep for the two coil positions.
sweepname = "CoilSweep"
@@ -152,15 +140,14 @@
param["CopyMesh"] = False
param["SolveWithCopiedMeshOnly"] = True
-# Solve parametric sweep
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Solve parametric sweep
+#
# Solve the parametric sweep directly so that results of all variations are available.
m3d.analyze_setup(sweepname)
-###############################################################################
-# Create expression for Bz
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create expression for Bz
+#
# Create an expression for Bz using the fields calculator.
Fields = m3d.odesign.GetModule("FieldsReporter")
@@ -171,11 +158,11 @@
Fields.CalcOp("Smooth")
Fields.AddNamedExpression("Bz", "Fields")
-###############################################################################
-# Plot mag(Bz) as a function of frequency
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot mag(Bz) as a function of frequency
+#
# Plot mag(Bz) as a function of frequency for both coil positions.
+# +
variations = {"Distance": ["All"], "Freq": ["All"], "Phase": ["0deg"], "Coil_Position": ["-20mm"]}
m3d.post.create_report(
expressions="mag(Bz)",
@@ -195,12 +182,13 @@
primary_sweep_variable="Distance",
plotname="mag(Bz) Along 'Line_AB' Coil",
)
+# -
-###############################################################################
-# Generate plot outside of AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate plot outside of AEDT
+#
# Generate the same plot outside AEDT.
+# +
variations = {"Distance": ["All"], "Freq": ["All"], "Phase": ["0deg"], "Coil_Position": ["All"]}
solutions = m3d.post.get_solution_data(
@@ -210,35 +198,32 @@
variations=variations,
primary_sweep_variable="Distance",
)
+# -
-###############################################################################
-# Set up sweep value and plot solution
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set up sweep value and plot solution
+#
# Set up a sweep value and plot the solution.
solutions.active_variation["Coil_Position"] = -0.02
solutions.plot()
-###############################################################################
-# Change sweep value and plot solution
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Change sweep value and plot solution
+#
# Change the sweep value and plot the solution again.
solutions.active_variation["Coil_Position"] = 0
solutions.plot()
-###############################################################################
-# Plot induced current density on surface of ladder plate
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot induced current density on surface of ladder plate
+#
# Plot the induced current density, ``"Mag_J"``, on the surface of the ladder plate.
surflist = modeler.get_object_faces("LadderPlate")
intrinsic_dict = {"Freq": "50Hz", "Phase": "0deg"}
m3d.post.create_fieldplot_surface(surflist, "Mag_J", intrinsincDict=intrinsic_dict, plot_name="Mag_J")
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT from the script engine, leaving both AEDT and the project open.
m3d.release_desktop(True, True)
diff --git a/examples/03-Maxwell/Maxwell_Control_Program.py b/examples/03-Maxwell/Maxwell_Control_Program.py
index 182bccaf34c..20b66d45e27 100644
--- a/examples/03-Maxwell/Maxwell_Control_Program.py
+++ b/examples/03-Maxwell/Maxwell_Control_Program.py
@@ -1,40 +1,35 @@
-"""
-Enabling Control Program in a Maxwell 2D Project
-------------------------------------------------
-This example shows how you can use PyAEDT to enable control program in a Maxwell 2D project.
-It shows how to create the geometry, load material properties from an Excel file and
-set up the mesh settings. Moreover, it focuses on post-processing operations, in particular how to
-plot field line traces, relevant for an electrostatic analysis.
-
-"""
-#################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Enabling Control Program in a Maxwell 2D Project
+
+# This example shows how you can use PyAEDT to enable control program in a Maxwell 2D project.
+# It shows how to create the geometry, load material properties from an Excel file and
+# set up the mesh settings. Moreover, it focuses on post-processing operations, in particular how to
+# plot field line traces, relevant for an electrostatic analysis.
+
+# ## Perform required imports
+#
# Perform required imports.
from pyaedt import downloads
from pyaedt import generate_unique_folder_name
from pyaedt import Maxwell2d
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-#################################################################################
-# Download .aedt file example
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download .aedt file example
+#
# Set local temporary folder to export the .aedt file to.
+
temp_folder = generate_unique_folder_name()
aedt_file = downloads.download_file("maxwell_ctrl_prg", "ControlProgramDemo.aedt", temp_folder)
ctrl_prg_file = downloads.download_file("maxwell_ctrl_prg", "timestep_only.py", temp_folder)
-##################################################################################
-# Launch Maxwell 2D
-# ~~~~~~~~~~~~~~~~~
+# ## Launch Maxwell 2D
+#
# Launch Maxwell 2D.
m2d = Maxwell2d(projectname=aedt_file,
@@ -42,46 +37,40 @@
new_desktop_session=True,
non_graphical=non_graphical)
-##################################################################################
-# Set active design
-# ~~~~~~~~~~~~~~~~~
+# ## Set active design
+#
# Set active design.
m2d.set_active_design("1 time step control")
-##################################################################################
-# Get design setup
-# ~~~~~~~~~~~~~~~~
+# ## Get design setup
+#
# Get design setup to enable the control program to.
setup = m2d.setups[0]
-##################################################################################
-# Enable control program
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Enable control program
+#
# Enable control program by giving the path to the file.
setup.enable_control_program(control_program_path=ctrl_prg_file)
-##################################################################################
-# Analyze setup
-# ~~~~~~~~~~~~~
+# ## Analyze setup
+#
# Analyze setup.
setup.analyze()
-##################################################################################
-# Plot results
-# ~~~~~~~~~~~~
+# ## Plot results
+#
# Plot Solved Results.
sols = m2d.post.get_solution_data("FluxLinkage(Winding1)",variations={"Time":["All"]}, primary_sweep_variable="Time")
sols.plot()
-###################################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
m2d.save_project()
diff --git a/examples/03-Maxwell/Maxwell_Magnet.py b/examples/03-Maxwell/Maxwell_Magnet.py
index 5a5abc53db4..7dc9c562265 100644
--- a/examples/03-Maxwell/Maxwell_Magnet.py
+++ b/examples/03-Maxwell/Maxwell_Magnet.py
@@ -1,29 +1,25 @@
-"""
-Maxwell 3D: magnet DC analysis
-------------------------------
-This example shows how you can use PyAEDT to create a Maxwell DC analysis,
-compute mass center, and move coordinate systems.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 3D: magnet DC analysis
+
+# This example shows how you can use PyAEDT to create a Maxwell DC analysis,
+# compute mass center, and move coordinate systems.
+
+# ## Perform required imports
+#
# Perform required imports.
from pyaedt import Maxwell3d
from pyaedt import generate_unique_project_name
import os
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
m3d = Maxwell3d(projectname=generate_unique_project_name(),
@@ -31,45 +27,39 @@
new_desktop_session=True,
non_graphical=non_graphical)
-###############################################################################
-# Set up Maxwell solution
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set up Maxwell solution
+#
# Set up the Maxwell solution to DC.
m3d.solution_type = m3d.SOLUTIONS.Maxwell3d.ElectroDCConduction
-###############################################################################
-# Create magnet
-# ~~~~~~~~~~~~~
+# ## Create magnet
+#
# Create a magnet.
magnet = m3d.modeler.create_box(position=[7, 4, 22], dimensions_list=[10, 5, 30], name="Magnet", matname="copper")
-###############################################################################
-# Create setup and assign voltage
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and assign voltage
+#
# Create the setup and assign a voltage.
m3d.assign_voltage(magnet.faces, 0)
m3d.create_setup()
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
m3d.plot(show=False, export_path=os.path.join(m3d.working_directory, "Image.jpg"), plot_air_objects=True)
-###############################################################################
-# Solve setup
-# ~~~~~~~~~~~
+# ## Solve setup
+#
# Solve the setup.
m3d.analyze()
-###############################################################################
-# Compute mass center
-# ~~~~~~~~~~~~~~~~~~~
+# ## Compute mass center
+#
# Compute mass center using the fields calculator.
m3d.post.ofieldsreporter.EnterScalarFunc("X")
@@ -86,36 +76,32 @@
m3d.post.ofieldsreporter.AddNamedExpression("CM_Z", "Fields")
m3d.post.ofieldsreporter.CalcStack("clear")
-###############################################################################
-# Get mass center
-# ~~~~~~~~~~~~~~~
+# ## Get mass center
+#
# Get mass center using the fields calculator.
xval = m3d.post.get_scalar_field_value("CM_X", None)
yval = m3d.post.get_scalar_field_value("CM_Y", None)
zval = m3d.post.get_scalar_field_value("CM_Z", None)
-###############################################################################
-# Create variables
-# ~~~~~~~~~~~~~~~~
+# ## Create variables
+#
# Create variables with mass center values.
m3d[magnet.name + "x"] = str(xval * 1e3) + "mm"
m3d[magnet.name + "y"] = str(yval * 1e3) + "mm"
m3d[magnet.name + "z"] = str(zval * 1e3) + "mm"
-###############################################################################
-# Create coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coordinate system
+#
# Create a parametric coordinate system.
cs1 = m3d.modeler.create_coordinate_system(
[magnet.name + "x", magnet.name + "y", magnet.name + "z"], reference_cs="Global", name=magnet.name + "CS"
)
-###############################################################################
-# Save and close
-# ~~~~~~~~~~~~~~
+# ## Save and close
+#
# Save the project and close AEDT.
m3d.save_project()
diff --git a/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py b/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py
index cab8575bbf2..9bff16e7a26 100644
--- a/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py
+++ b/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py
@@ -1,12 +1,10 @@
-"""
-Maxwell 3D: Transformer
------------------------
-This example shows how you can use PyAEDT to set core loss given a set
-of Power-Volume [kw/m^3] curves at different frequencies.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Maxwell 3D: Transformer
+
+# This example shows how you can use PyAEDT to set core loss given a set
+# of Power-Volume [kw/m^3] curves at different frequencies.
+
+# ## Perform required imports
+#
# Perform required imports.
from pyaedt import downloads
@@ -15,11 +13,11 @@
from pyaedt.generic.constants import unit_converter
from pyaedt.generic.general_methods import read_csv_pandas
-#################################################################################
-# Download .aedt file example
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download .aedt file example
+#
# Set local temporary folder to export the .aedt file to.
+# +
temp_folder = generate_unique_folder_name()
aedt_file = downloads.download_file("core_loss_transformer", "Ex2-PlanarTransformer_2023R2.aedtz", temp_folder)
freq_curve_csv_25kHz = downloads.download_file("core_loss_transformer", "mf3_25kHz.csv", temp_folder)
@@ -47,10 +45,10 @@
data = read_csv_pandas(filename=freq_curve_csv_1MHz)
curves_csv_1MHz = list(zip(data[data.columns[0]],
data[data.columns[1]]))
+# -
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
m3d = Maxwell3d(projectname=aedt_file,
@@ -59,9 +57,8 @@
new_desktop_session=True,
non_graphical=False)
-###############################################################################
-# Set core loss at frequencies
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set core loss at frequencies
+#
# Create a new material, create a dictionary of Power-Volume [kw/m^3] points for a set of frequencies
# retrieved from datasheet provided by supplier and finally set Power-Ferrite core loss model.
@@ -82,9 +79,8 @@
coefficients = m3d.materials[mat.name].get_core_loss_coefficients(points_list_at_freq=pv,
coefficient_setup="kw_per_cubic_meter")
-###################################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
m3d.save_project()
diff --git a/examples/03-Maxwell/Readme.txt b/examples/03-Maxwell/Readme.txt
deleted file mode 100644
index 6eb8131b407..00000000000
--- a/examples/03-Maxwell/Readme.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Maxwell examples
-~~~~~~~~~~~~~~~~
-These examples use PyAEDT to show some end-to-end workflows for Maxwell 2D and
-Maxwell 3D. This includes model generation, setup, meshing, and postprocessing.
-Examples cover different Maxwell solution types (Eddy Current, Magnetostatic,
-and Transient).
diff --git a/examples/03-Maxwell/index.rst b/examples/03-Maxwell/index.rst
new file mode 100644
index 00000000000..3c3f7263280
--- /dev/null
+++ b/examples/03-Maxwell/index.rst
@@ -0,0 +1,20 @@
+Maxwell examples
+~~~~~~~~~~~~~~~~
+These examples use PyAEDT to show some end-to-end workflows for Maxwell 2D and
+Maxwell 3D. This includes model generation, setup, meshing, and postprocessing.
+Examples cover different Maxwell solution types (Eddy Current, Magnetostatic,
+and Transient).
+
+.. nbgallery::
+
+ Maxwell2D_DCConduction.py
+ Maxwell2D_Electrostatic.py
+ Maxwell2D_NissanLeaf.py
+ Maxwell2D_Transient.py
+ Maxwell3DTeam7.py
+ Maxwell3D_Choke.py
+ Maxwell3D_Segmentation.py
+ Maxwell3D_Team3_bath_plate.py
+ Maxwell_Control_Program.py
+ Maxwell_Magnet.py
+ Maxwell_Transformer_Coreloss.py
\ No newline at end of file
diff --git a/examples/04-Icepak/Icepak_3DComponents_Example.py b/examples/04-Icepak/Icepak_3DComponents_Example.py
index 586fbfac7ec..2edc1771aa0 100644
--- a/examples/04-Icepak/Icepak_3DComponents_Example.py
+++ b/examples/04-Icepak/Icepak_3DComponents_Example.py
@@ -1,13 +1,10 @@
-"""
-Icepak: thermal analysis with 3D components
--------------------------------------------
-This example shows how to create a thermal analysis of an electronic package by taking advantage of 3D components and
-features added by PyAEDT.
-"""
-
-###############################################################################
-# Import PyAEDT and download files
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# # Icepak: thermal analysis with 3D components
+
+# This example shows how to create a thermal analysis of an electronic package by
+# taking advantage of 3D components and features added by PyAEDT.
+
+# ## Import PyAEDT and download files
+#
# Perform import of required classes from the ``pyaedt`` package and import the ``os`` package.
from pyaedt import Icepak, generate_unique_folder_name, downloads, settings
@@ -18,24 +15,21 @@
temp_folder = generate_unique_folder_name()
package_temp_name, qfp_temp_name = downloads.download_icepak_3d_component(temp_folder)
-###############################################################################
-# Set AEDT version
-# ~~~~~~~~~~~~~~~~
+# ## Set AEDT version
+#
# Set AEDT version.
aedt_version = "2023.2"
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Create heatsink
-# ~~~~~~~~~~~~~~~
+# ## Create heatsink
+#
# Open a new project in non-graphical mode.
ipk = Icepak(projectname=os.path.join(temp_folder, "Heatsink.aedt"),
@@ -49,6 +43,7 @@
ipk.modeler.get_object_from_name("Region").delete()
# Definition of heatsink with boxes
+
hs_base = ipk.modeler.create_box(position=[0, 0, 0], dimensions_list=[37.5, 37.5, 2], name="HS_Base")
hs_base.material_name = "Al-Extruded"
hs_fin = ipk.modeler.create_box(position=[0, 0, 2], dimensions_list=[37.5, 1, 18], name="HS_Fin1")
@@ -58,6 +53,7 @@
ipk.plot(show=False, export_path=os.path.join(temp_folder, "Heatsink.jpg"))
# Definition of a mesh region. First a non-model box is created, then the mesh region is assigned
+
mesh_box = ipk.modeler.create_box(position=[-2, -2, -3], dimensions_list=[41.5, 41.5, 24])
mesh_box.model = False
mesh_region = ipk.mesh.assign_mesh_region([mesh_box.name])
@@ -71,6 +67,8 @@
mesh_region.update()
# Assignment of monitor objects.
+
+# +
hs_fin5_object = ipk.modeler.get_object_from_name("HS_Fin1_5")
point_monitor_position = [0.5 * (hs_base.bounding_box[i] + hs_base.bounding_box[i + 3]) for i in range(2)] + [
hs_fin5_object.bounding_box[-1]] # average x,y, top z
@@ -79,9 +77,11 @@
monitor_name="TopPoint")
ipk.monitor.assign_face_monitor(hs_base.bottom_face_z.id, monitor_quantity="Temperature", monitor_name="Bottom")
ipk.monitor.assign_point_monitor_in_object("HS_Fin1_5", monitor_quantity="Temperature", monitor_name="Fin5Center")
+# -
# Export the heatsink 3D component and close project. auxiliary_dict is set to true in order to export the
# monitor objects along with the .a3dcomp file.
+
os.mkdir(os.path.join(temp_folder, "componentLibrary"))
ipk.modeler.create_3dcomponent(
os.path.join(temp_folder, "componentLibrary", "Heatsink.a3dcomp"),
@@ -90,14 +90,15 @@
)
ipk.close_project(save_project=False)
-###############################################################################
-# Create QFP
-# ~~~~~~~~~~
+# ## Create QFP
+#
# Download and open a project containing a QPF.
+
ipk = Icepak(projectname=qfp_temp_name)
ipk.plot(show=False, export_path=os.path.join(temp_folder, "QFP2.jpg"))
# Create dataset for power dissipation.
+
x_datalist = [45, 53, 60, 70]
y_datalist = [0.5, 3, 6, 9]
ipk.create_dataset(
@@ -114,6 +115,7 @@
)
# Assign source power condition to the die.
+
ipk.create_source_power(
"DieSource",
thermal_dependent_dataset="PowerDissipationDataset",
@@ -121,6 +123,7 @@
)
# Assign thickness to the die attach surface.
+
ipk.create_conduting_plate(face_id="Die_Attach",
thermal_specification="Thickness",
shell_conduction=True,
@@ -130,11 +133,13 @@
)
# Assign monitor objects.
+
ipk.monitor.assign_point_monitor_in_object("QFP2_die", monitor_quantity="Temperature", monitor_name="DieCenter")
ipk.monitor.assign_surface_monitor("Die_Attach", monitor_quantity="Temperature", monitor_name="DieAttach")
# Export the QFP 3D component and close project. Here the auxiliary dictionary allows exporting not only the monitor
# objects but also the dataset used for the power source assignment.
+
ipk.modeler.create_3dcomponent(
os.path.join(temp_folder, "componentLibrary", "QFP.a3dcomp"),
component_name="QFP",
@@ -143,9 +148,8 @@
)
ipk.release_desktop(False, False)
-###############################################################################
-# Create electronic package
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create electronic package
+#
# Download and open a project containing the electronic package.
ipk = Icepak(projectname=package_temp_name,
specified_version=aedt_version,
@@ -155,6 +159,8 @@
# The heatsink and the QFP are missing. They can be inserted as 3d components. The auxiliary files are needed since
# the aim is to import also monitor objects and datasets. Also, a coordinate system is created for the heatsink so
# that it is placed on top of the AGP.
+
+# +
agp = ipk.modeler.get_object_from_name("AGP_IDF")
cs = ipk.modeler.create_coordinate_system(
origin=[agp.bounding_box[0], agp.bounding_box[1], agp.bounding_box[-1]],
@@ -171,8 +177,10 @@
comp_file=os.path.join(temp_folder, "componentLibrary", "QFP.a3dcomp"),
targetCS="Global", auxiliary_dict=True)
ipk.plot(show=False, export_path=os.path.join(temp_folder, "electronic_package.jpg"))
+# -
# Create a coordinate system at the xmin, ymin, zmin of the model
+
bounding_box = ipk.modeler.get_model_bounding_box()
cs_pcb_assembly = ipk.modeler.create_coordinate_system(
origin=[bounding_box[0], bounding_box[1], bounding_box[2]],
@@ -185,6 +193,8 @@
# Export of the whole assembly as 3d component and close project. First, a flattening is needed because nested 3d
# components are not natively supported. Then it is possible to export the whole package as 3d component. Here the
# auxiliary dictionary is needed to export monitor objects, datasets and native components.
+
+# +
ipk.flatten_3d_components()
ipk.modeler.create_3dcomponent(
component_file=os.path.join(temp_folder, "componentLibrary", "PCBAssembly.a3dcomp"),
@@ -194,9 +204,8 @@
reference_cs="PCB_Assembly"
)
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
ipk.release_desktop(True, True)
diff --git a/examples/04-Icepak/Icepak_CSV_Import.py b/examples/04-Icepak/Icepak_CSV_Import.py
index 064fbda03c1..d4e63393025 100644
--- a/examples/04-Icepak/Icepak_CSV_Import.py
+++ b/examples/04-Icepak/Icepak_CSV_Import.py
@@ -1,12 +1,10 @@
-"""
-Icepak: Creating blocks and assigning materials and power
--------------------------------------
-This example shows how to create different types of blocks and assign power and material to them using
-a *.csv input file
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Icepak: Creating blocks and assigning materials and power
+
+# This example shows how to create different types of blocks and assign power and material to them using
+# a *.csv input file
+
+# ## Perform required imports
+#
# Perform required imports including the operating system, regular expression, csv, Ansys PyAEDT
# and its boundary objects.
@@ -17,19 +15,18 @@
import pyaedt
from pyaedt.modules.Boundary import BoundaryObject
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Download and open project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download and open project
+#
# Download the project, open it, and save it to the temporary folder.
+# +
temp_folder = pyaedt.generate_unique_folder_name()
ipk = pyaedt.Icepak(projectname=os.path.join(temp_folder, "Icepak_CSV_Import.aedt"),
@@ -39,13 +36,14 @@
)
ipk.autosave_disable()
+# -
# Create the PCB as a simple block.
+
board = ipk.modeler.create_box([-30.48, -27.305, 0], [146.685, 71.755, 0.4064], "board_outline", matname="FR-4_Ref")
-###############################################################################
-# Blocks creation with a CSV file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Blocks creation with a CSV file
+#
# The CSV file lists the name of blocks, their type and material properties.
# Block types (solid, network, hollow), block name, block starting and end points, solid material, and power are listed.
# Hollow and network blocks do not need the material name.
@@ -54,15 +52,15 @@
#
# The following image does not show the entire rows and data and only serves as a sample.
#
-# .. image:: ../../_static/CSV_Import.png
-# :width: 400
-# :alt: CSV Screenshot.
+#
+#
#
#
# In this step the code will loop over the csv file lines and creates the blocks.
# It will create solid blocks and assign BCs.
# Every row of the csv has information of a particular block.
+# +
filename = pyaedt.downloads.download_file('icepak', 'blocks-list.csv', destination=temp_folder)
with open(filename, 'r') as csv_file:
@@ -102,9 +100,8 @@
monitor_quantity="Temperature",
monitor_name=row["name"])
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
ipk.release_desktop(True, True)
diff --git a/examples/04-Icepak/Icepak_ECAD_Import.py b/examples/04-Icepak/Icepak_ECAD_Import.py
index 2d72c16c356..8f45b17bf1a 100644
--- a/examples/04-Icepak/Icepak_ECAD_Import.py
+++ b/examples/04-Icepak/Icepak_ECAD_Import.py
@@ -1,41 +1,34 @@
-"""
-Icepak: Importing a PCB and its components via IDF and EDB
--------------------------------------
-This example shows how to import a PCB and its components using IDF files (*.ldb/*.bdf).
-The *.emn/*.emp combination can also be used in a similar way.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports including the operating system, Ansys PyAEDT packages.
+# # Icepak: Importing a PCB and its components via IDF and EDB
+
+# This example shows how to import a PCB and its components using IDF files (*.ldb/*.bdf).
+# The *.emn/*.emp combination can also be used in a similar way.
+# ## Perform required imports
+#
+# Perform required imports including the operating system, Ansys PyAEDT packages.
# Generic Python packages
import os
# PyAEDT Packages
+
import pyaedt
-from pyaedt import Icepak
-from pyaedt import Desktop
from pyaedt import Hfss3dLayout
-from pyaedt.modules.Boundary import BoundaryObject
-
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Download and open project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download and open project
+#
# Download the project, open it, and save it to the temporary folder.
+# +
temp_folder = pyaedt.generate_unique_folder_name()
ipk = pyaedt.Icepak(projectname=os.path.join(temp_folder, "Icepak_ECAD_Import.aedt"),
@@ -44,30 +37,23 @@
non_graphical=non_graphical
)
-ipk.autosave_disable() # Saves the project
+ipk.autosave_disable()
+# -
-###############################################################################
-# Import the IDF files
-# ~~~~~~~~~~~~~~~~~~~~
-# Sample *.bdf and *.ldf files are presented here.
-#
-#
-# .. image:: ../../_static/bdf.png
-# :width: 400
-# :alt: BDF image.
+# ## Import the IDF files
#
+# Sample *.bdf and *.ldf files are presented here.
#
-# .. image:: ../../_static/ldf.png
-# :width: 400
-# :alt: LDF image.
+#
#
+#
#
# Imports the idf files with several filtering options including caps, resistors, inductors, power, size, ...
# There are also options for the PCB creation (number o flayers, copper percentages, layer sizes).
# In this example, the default values are used for the PCB.
# The imported PCB here will be deleted later and replaced by a PCB that has the trace information for higher accuracy.
-
+# +
def_path = pyaedt.downloads.download_file('icepak/Icepak_ECAD_Import/A1_uprev.aedb','edb.def',temp_folder)
board_path = pyaedt.downloads.download_file('icepak/Icepak_ECAD_Import/','A1.bdf',temp_folder)
library_path = pyaedt.downloads.download_file('icepak/Icepak_ECAD_Import/','A1.ldf',temp_folder)
@@ -84,47 +70,46 @@
model_board_as_rect=False, model_device_as_rect=True,
cutoff_height='5mm', component_lib='')
-###############################################################################
-# Fit to scale, save the project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Fit to scale, save the project
+#
ipk.modeler.fit_all() # scales to fit all objects in AEDT
ipk.save_project() # saves the project
-###############################################################################
-# Add an HFSS 3D Layout design with the layout information of the PCB
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Layout_name = 'A1_uprev' # 3D layout name available for import, the extension of .aedb should not be listed here
-
-hfss3dLO = Hfss3dLayout('Icepak_ECAD_Import', 'PCB_temp') # adding a dummy HFSS 3D layout to the current project
-
-#edb_full_path = os.path.join(os.getcwd(), Layout_name+'.aedb\edb.def') # path to the EDB file
-hfss3dLO.import_edb(def_path) # importing the EDB file
-hfss3dLO.save_project() # save the new project so files are stored in the path
+# ## Add an HFSS 3D Layout design with the layout information of the PCB
+#
-ipk.delete_design(name='PCB_temp', fallback_design=None) # deleting the dummy layout from the original project
+# 3D layout name available for import, the extension of .aedb should not be listed here
+Layout_name = 'A1_uprev'
+# Adding a dummy HFSS 3D layout to the current project
+hfss3dLO = Hfss3dLayout('Icepak_ECAD_Import', 'PCB_temp')
+# Importing the EDB file
+hfss3dLO.import_edb(def_path)
+# Save the new project so files are stored in the path
+hfss3dLO.save_project()
+# Deleting the dummy layout from the original project
+ipk.delete_design(name='PCB_temp', fallback_design=None)
# This part creates a 3D component PCB in Icepak from the imported EDB file
# 1 watt is assigned to the PCB as power input
+# +
component_name = "PCB_ECAD"
odb_path = os.path.join(temp_folder, 'icepak/Icepak_ECAD_Import/'+Layout_name+'.aedt')
ipk.create_pcb_from_3dlayout(
component_name, odb_path, Layout_name, resolution=2, extenttype="Polygon", outlinepolygon='poly_0',
custom_x_resolution=None, custom_y_resolution=None, power_in=1)
+# -
-###############################################################################
-# Delete PCB objects
-# ~~~~~~~~~~~~~~~~~~
+# ## Delete PCB objects
+#
# Delete the PCB object from IDF import.
ipk.modeler.delete_objects_containing("IDF_BoardOutline", False)
-###############################################################################
-# Compute power budget
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Compute power budget
+#
# Creates a setup to be able to calculate the power
ipk.create_setup("setup1")
@@ -132,9 +117,8 @@
power_budget, total = ipk.post.power_budget("W")
print(total)
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
ipk.release_desktop(True, True)
\ No newline at end of file
diff --git a/examples/04-Icepak/Icepak_Example.py b/examples/04-Icepak/Icepak_Example.py
index f66fe1f7501..a559680a3fb 100644
--- a/examples/04-Icepak/Icepak_Example.py
+++ b/examples/04-Icepak/Icepak_Example.py
@@ -1,30 +1,27 @@
-"""
-Icepak: graphic card thermal analysis
--------------------------------------
-This example shows how you can use PyAEDT to create a graphic card setup in Icepak and postprocess results.
-The example file is an Icepak project with a model that is already created and has materials assigned.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Icepak: graphic card thermal analysis
+
+# This example shows how you can use PyAEDT to create a graphic card setup in Icepak and postprocess results.
+# The example file is an Icepak project with a model that is already created and has materials assigned.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Download and open project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download and open project
+#
# Download the project, open it, and save it to the temporary folder.
+# +
temp_folder = pyaedt.generate_unique_folder_name()
project_temp_name = pyaedt.downloads.download_icepak(temp_folder)
@@ -35,34 +32,31 @@
)
ipk.autosave_disable()
+# -
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
ipk.plot(show=False, export_path=os.path.join(temp_folder, "Graphics_card.jpg"), plot_air_objects=False)
-###############################################################################
-# Create source blocks
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Create source blocks
+#
# Create source blocks on the CPU and memories.
ipk.create_source_block("CPU", "25W")
ipk.create_source_block(["MEMORY1", "MEMORY1_1"], "5W")
-###############################################################################
-# Assign openings and grille
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign openings and grille
+#
# Assign openings and a grille.
region = ipk.modeler["Region"]
ipk.assign_openings(air_faces=region.bottom_face_x.id)
ipk.assign_grille(air_faces=region.top_face_x.id, free_area_ratio=0.8)
-###############################################################################
-# Assign mesh regions
-# ~~~~~~~~~~~~~~~~~~~
+# ## Assign mesh regions
+#
# Assign a mesh region to the heat sink and CPU.
mesh_region = ipk.mesh.assign_mesh_region(objectlist=["HEAT_SINK", "CPU"])
@@ -73,9 +67,8 @@
mesh_region.MaxLevels = "2"
mesh_region.update()
-###############################################################################
-# Assign point monitor
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Assign point monitor
+#
# Assign a point monitor and set it up.
ipk.assign_point_monitor(point_position=["-35mm", "3.6mm", "-86mm"], monitor_name="TemperatureMonitor1")
@@ -87,11 +80,11 @@
setup1.props["Linear Solver Type - Temperature"] = "flex"
ipk.save_project()
-###############################################################################
-# Solve project and postprocess
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Solve project and postprocess
+#
# Solve the project and plot temperatures.
+# +
quantity_name = "SurfTemperature"
surflist = [i.id for i in ipk.modeler["CPU"].faces]
surflist += [i.id for i in ipk.modeler["MEMORY1"].faces]
@@ -100,12 +93,11 @@
plot5 = ipk.post.create_fieldplot_surface(surflist, "SurfTemperature")
-
ipk.analyze()
+# -
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
ipk.release_desktop(True, True)
diff --git a/examples/04-Icepak/Sherlock_Example.py b/examples/04-Icepak/Sherlock_Example.py
index 3c7ac08b0b1..0e9f0a57d23 100644
--- a/examples/04-Icepak/Sherlock_Example.py
+++ b/examples/04-Icepak/Sherlock_Example.py
@@ -1,12 +1,10 @@
-"""
-Icepak: setup from Sherlock inputs
------------------------------------
-This example shows how you can create an Icepak project from Sherlock
-files (STEP and CSV) and an AEDB board.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Icepak: setup from Sherlock inputs
+
+# This example shows how you can create an Icepak project from Sherlock
+# files (STEP and CSV) and an AEDB board.
+
+# ## Perform required imports
+#
# Perform required imports and set paths.
import time
@@ -15,20 +13,19 @@
import datetime
# Set paths
+
project_folder = pyaedt.generate_unique_folder_name()
input_dir = pyaedt.downloads.download_sherlock(destination=project_folder)
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` value either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define input variables. The following code creates all input variables that are needed
# to run this example.
@@ -40,11 +37,11 @@
stackup_thickness = 2.11836
outline_polygon_name = "poly_14188"
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode.
+# +
d = pyaedt.launch_desktop(specified_version="2023.2", non_graphical=non_graphical, new_desktop_session=True)
start = time.time()
@@ -53,120 +50,107 @@
validation = os.path.join(project_folder, "validation.log")
file_path = os.path.join(input_dir, component_step)
project_name = os.path.join(project_folder, component_step[:-3] + "aedt")
+# -
-###############################################################################
-# Create Icepak project
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Create Icepak project
+#
# Create an Icepak project.
ipk = pyaedt.Icepak(project_name)
-###############################################################################
-# Delete region to speed up import
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Delete region to speed up import
+#
# Delete the region and disable autosave to speed up the import.
d.disable_autosave()
ipk.modeler.delete("Region")
component_name = "from_ODB"
-###############################################################################
-# Import PCB from AEDB file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import PCB from AEDB file
+#
# Import a PCB from an AEDB file.
odb_path = os.path.join(input_dir, aedt_odb_project)
ipk.create_pcb_from_3dlayout(component_name=component_name, project_name=odb_path, design_name=aedt_odb_design_name,
extenttype="Polygon")
-###############################################################################
-# Create offset coordinate system
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create offset coordinate system
+#
# Create an offset coordinate system to match ODB++ with the
# Sherlock STEP file.
ipk.modeler.create_coordinate_system(origin=[0, 0, stackup_thickness / 2], mode="view", view="XY")
-###############################################################################
-# Import CAD file
-# ~~~~~~~~~~~~~~~
+# ## Import CAD file
+#
# Import a CAD file.
ipk.modeler.import_3d_cad(file_path, refresh_all_ids=False)
-###############################################################################
-# Save CAD file
-# ~~~~~~~~~~~~~
+# ## Save CAD file
+#
# Save the CAD file and refresh the properties from the parsing of the AEDT file.
ipk.save_project(refresh_obj_ids_after_save=True)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
ipk.plot(show=False, export_path=os.path.join(project_folder, "Sherlock_Example.jpg"), plot_air_objects=False)
-###############################################################################
-# Delete PCB objects
-# ~~~~~~~~~~~~~~~~~~
+# ## Delete PCB objects
+#
# Delete the PCB objects.
ipk.modeler.delete_objects_containing("pcb", False)
-###############################################################################
-# Create region
-# ~~~~~~~~~~~~~
+# ## Create region
+#
# Create an air region.
ipk.modeler.create_air_region(*[20, 20, 300, 20, 20, 300])
-###############################################################################
-# Assign materials
-# ~~~~~~~~~~~~~~~~
+# ## Assign materials
+#
# Assign materials from Sherlock file.
ipk.assignmaterial_from_sherlock_files(component_list, material_list)
-###############################################################################
-# Delete objects with no material assignments
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Delete objects with no material assignments
+#
# Delete objects with no materials assignments.
no_material_objs = ipk.modeler.get_objects_by_material("")
ipk.modeler.delete(no_material_objs)
ipk.save_project()
-###############################################################################
-# Assign power to component blocks
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign power to component blocks
+#
# Assign power to component blocks.
all_objects = ipk.modeler.object_names
-###############################################################################
-# Assign power blocks
-# ~~~~~~~~~~~~~~~~~~~
+# ## Assign power blocks
+#
# Assign power blocks from the Sherlock file.
total_power = ipk.assign_block_from_sherlock_file(csv_name=component_list)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model again now that materials are assigned.
ipk.plot(show=False, export_path=os.path.join(project_folder, "Sherlock_Example.jpg"), plot_air_objects=False)
-###############################################################################
-# Set up boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Set up boundaries
+#
# Set up boundaries.
# Mesh settings that is tailored for PCB
# Max iterations is set to 20 for quick demonstration, please increase to at least 100 for better accuracy.
+# +
ipk.globalMeshSettings(3, gap_min_elements='1', noOgrids=True, MLM_en=True,
MLM_Type='2D', edge_min_elements='2', object='Region')
@@ -177,56 +161,51 @@
setup1.props["Secondary Gradient"] = True
setup1.props["Convergence Criteria - Max Iterations"] = 10
ipk.assign_openings(ipk.modeler.get_object_faces("Region"))
+# -
-###############################################################################
-# Create point monitor
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Create point monitor
+#
point1 = ipk.assign_point_monitor(ipk.modeler["COMP_U10"].top_face_z.center, monitor_name="Point1")
ipk.modeler.set_working_coordinate_system("Global")
line = ipk.modeler.create_polyline([ipk.modeler["COMP_U10"].top_face_z.vertices[0].position, ipk.modeler["COMP_U10"].top_face_z.vertices[2].position], non_model=True)
ipk.post.create_report(expressions="Point1.Temperature", primary_sweep_variable="X")
-###############################################################################
-# Check for intersections
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Check for intersections
+#
# Check for intersections using validation and fix them by
# assigning priorities.
ipk.assign_priority_on_intersections()
-###############################################################################
-# Compute power budget
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Compute power budget
+#
power_budget, total = ipk.post.power_budget("W" )
print(total)
-###############################################################################
-# Analyze the model
-# ~~~~~~~~~~~~~~~~~
+# ## Analyze the model
+#
ipk.analyze(num_cores=4, num_tasks=4)
ipk.save_project()
-###############################################################################
-# Get solution data and plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get solution data and plots
+#
plot1 = ipk.post.create_fieldplot_surface(ipk.modeler["COMP_U10"].faces, "SurfTemperature")
ipk.post.plot_field("SurfPressure",ipk.modeler["COMP_U10"].faces,export_path=ipk.working_directory, show=False)
-###############################################################################
-# Save project and release AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and release AEDT
+#
# Save the project and release AEDT.
+# +
ipk.save_project()
end = time.time() - start
print("Elapsed time: {}".format(datetime.timedelta(seconds=end)))
print("Project Saved in {} ".format(ipk.project_file))
ipk.release_desktop()
-
-
+# -
diff --git a/examples/04-Icepak/_static/CSV_Import.png b/examples/04-Icepak/_static/CSV_Import.png
new file mode 100644
index 00000000000..b73cd592054
Binary files /dev/null and b/examples/04-Icepak/_static/CSV_Import.png differ
diff --git a/examples/04-Icepak/_static/bdf.png b/examples/04-Icepak/_static/bdf.png
new file mode 100644
index 00000000000..ad9a532a3f8
Binary files /dev/null and b/examples/04-Icepak/_static/bdf.png differ
diff --git a/examples/04-Icepak/_static/ldf.png b/examples/04-Icepak/_static/ldf.png
new file mode 100644
index 00000000000..43646374ead
Binary files /dev/null and b/examples/04-Icepak/_static/ldf.png differ
diff --git a/examples/04-Icepak/Readme.txt b/examples/04-Icepak/index.rst
similarity index 53%
rename from examples/04-Icepak/Readme.txt
rename to examples/04-Icepak/index.rst
index f7bc280fad1..8cffba8a873 100644
--- a/examples/04-Icepak/Readme.txt
+++ b/examples/04-Icepak/index.rst
@@ -3,3 +3,10 @@ Icepak examples
These examples use PyAEDT to show end-to-end workflows for Icepak. This includes
schematic generation, setup, and thermal postprocessing.
+.. nbgallery::
+
+ Icepak_3DComponents_Example.py
+ Icepak_CSV_Import.py
+ Icepak_ECAD_Import.py
+ Icepak_Example.py
+ Sherlock_Example.py
diff --git a/examples/05-Q3D/Q2D_Armoured_Cable.py b/examples/05-Q3D/Q2D_Armoured_Cable.py
index 27583bd977f..1222bdbaa6d 100644
--- a/examples/05-Q3D/Q2D_Armoured_Cable.py
+++ b/examples/05-Q3D/Q2D_Armoured_Cable.py
@@ -1,25 +1,21 @@
-"""
-Q2D: Cable parameter identification
----------------------------------------------------
-This example shows how you can use PyAEDT to perform these tasks:
+# # Q2D: Cable parameter identification
- - Create a Q2D design using the Modeler primitives and importing part of the geometry.
- - Set up the entire simulation.
- - Link the solution to a Simplorer design.
+# This example shows how you can use PyAEDT to perform these tasks:
+#
+# - Create a Q2D design using the Modeler primitives and importing part of the geometry.
+# - Set up the entire simulation.
+# - Link the solution to a Simplorer design.
+#
+# For cable information, see `4 Core Armoured Power Cable `_
- For cable information, see `4 Core Armoured Power Cable `_
-
-"""
-#################################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
import pyaedt
import math
-#################################################################################
-# Initialize core strand dimensions and positions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize core strand dimensions and positions
+#
# Initialize cable sizing - radii in mm.
c_strand_radius = 2.575
@@ -28,9 +24,8 @@
core_xlpe_ins_thickness = 0.5
core_xy_coord = math.ceil(3 * c_strand_radius + 2 * core_xlpe_ins_thickness)
-#################################################################################
-# Initialize filling and sheath dimensions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize filling and sheath dimensions
+#
# Initialize radii of further structures incrementally adding thicknesses.
filling_radius = 1.4142 * (core_xy_coord + 3 * c_strand_radius + core_xlpe_ins_thickness + 0.5)
@@ -39,18 +34,16 @@
armour_radius = inner_sheath_radius + armour_thickness
outer_sheath_radius = armour_radius + 2
-#################################################################################
-# Initialize armature strand dimensions
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize armature strand dimensions
+#
# Initialize radii.
armour_centre_pos = inner_sheath_radius + armour_thickness / 2.0
arm_strand_rad = armour_thickness / 2.0 - 0.2
n_arm_strands = 30
-#################################################################################
-# Initialize dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize dictionaries
+#
# Initialize dictionaries that contain all the definitions for the design
# variables and output variables.
@@ -72,9 +65,8 @@
"n_arm_strands": str(n_arm_strands)
}
-#################################################################################
-# Initialize Q2D
-# ~~~~~~~~~~~~~~
+# ## Initialize Q2D
+#
# Initialize Q2D, providing the version, path to the project, and the design
# name and type.
@@ -86,9 +78,8 @@
tb_design_name = 'CableSystem'
q2d = pyaedt.Q2d(projectname=project_name, designname=q2d_design_name, specified_version=desktop_version)
-##########################################################
-# Define variables from dictionaries
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define variables from dictionaries
+#
# Define design variables from the created dictionaries.
for k, v in core_params.items():
@@ -98,18 +89,16 @@
for k, v in armour_params.items():
q2d[k] = v
-##########################################################
-# Create object to access 2D modeler
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create object to access 2D modeler
+#
# Create the ``mod2D`` object to access the 2D modeler easily.
mod2D = q2d.modeler
mod2D.delete()
mod2D.model_units = "mm"
-#################################################################################
-# Initialize required material properties
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Initialize required material properties
+#
# Cable insulators require the definition of specific materials since they are not included in the Sys Library.
# Plastic, PE (cross-linked, wire, and cable grade)
@@ -118,15 +107,16 @@
mat_pe_cable_grade.permittivity = "2.09762"
mat_pe_cable_grade.dielectric_loss_tangent = "0.000264575"
mat_pe_cable_grade.update()
+
# Plastic, PP (10% carbon fiber)
+
mat_pp = q2d.materials.add_material("plastic_pp_carbon_fiber")
mat_pp.conductivity = "0.0003161"
mat_pp.update()
-#####################################################################################
-# Create geometry for core strands, filling, and XLPE insulation
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for core strands, filling, and XLPE insulation
+# +
mod2D.create_coordinate_system(['c_strand_xy_coord', 'c_strand_xy_coord', '0mm'], name='CS_c_strand_1')
mod2D.set_working_coordinate_system('CS_c_strand_1')
c1_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'c_strand_radius', name='c_strand_1', matname='copper')
@@ -146,42 +136,33 @@
all_obj_names = q2d.get_all_conductors_names() + q2d.get_all_dielectrics_names()
mod2D.duplicate_around_axis(all_obj_names, cs_axis="Z", angle=360 / cable_n_cores, nclones=4)
cond_names = q2d.get_all_conductors_names()
+# +
-#####################################################################################
-# Create geometry for filling object
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for filling object
filling_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'filling_radius', name='Filling',
matname='plastic_pp_carbon_fiber')
filling_id.color = (255, 255, 180)
-#####################################################################################
-# Create geometry for inner sheath object
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for inner sheath object
inner_sheath_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'inner_sheath_radius', name='InnerSheath',
matname='PVC plastic')
inner_sheath_id.color = (0, 0, 0)
-#####################################################################################
-# Create geometry for armature fill
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for armature fill
arm_fill_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'armour_radius', name='ArmourFilling',
matname='plastic_pp_carbon_fiber')
arm_fill_id.color = (255, 255, 255)
-#####################################################################################
-# Create geometry for outer sheath
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for outer sheath
outer_sheath_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'outer_sheath_radius', name='OuterSheath',
matname='PVC plastic')
outer_sheath_id.color = (0, 0, 0)
-#####################################################################################
-# Create geometry for armature steel strands
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create geometry for armature steel strands
arm_strand_1_id = mod2D.create_circle(['0mm', 'armour_centre_pos', '0mm'], '1.1mm', name='arm_strand_1',
matname='steel_stainless')
@@ -189,16 +170,12 @@
arm_strand_1_id.duplicate_around_axis('Z', '360deg/n_arm_strands', nclones='n_arm_strands')
arm_strand_names = mod2D.get_objects_w_string('arm_strand')
-#####################################################################################
-# Create region
-# ~~~~~~~~~~~~~
+# ## Create region
region = q2d.modeler.create_region([500, 500, 500, 500, 0, 0])
region.material_name = "vacuum"
-##########################################################
-# Assign conductors and reference ground
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign conductors and reference ground
obj = [q2d.modeler.get_object_from_name(i) for i in cond_names]
[q2d.assign_single_conductor(name='C1' + str(obj.index(i) + 1), target_objects=i, conductor_type='SignalLine') for i
@@ -207,18 +184,14 @@
q2d.assign_single_conductor(name="gnd", target_objects=obj, conductor_type="ReferenceGround")
mod2D.fit_all()
-##########################################################
-# Assign design settings
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign design settings
lumped_length = "100m"
q2d_des_settings = q2d.design_settings()
q2d_des_settings['LumpedLength'] = lumped_length
q2d.change_design_settings(q2d_des_settings)
-##########################################################
-# Insert setup and frequency sweep
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Insert setup and frequency sweep
q2d_setup = q2d.create_setup(setupname=setup_name)
q2d_sweep = q2d_setup.add_sweep(sweepname=sweep_name)
@@ -229,21 +202,15 @@
q2d_sweep.props["RangeSamples"] = 1
q2d_sweep.update()
-##########################################################
-# Analyze setup
-# ~~~~~~~~~~~~~
+# ## Analyze setup
# q2d.analyze(setup_name=setup_name)
-###################################################################
-# Add a Simplorer/Twin Builder design and the Q3D dynamic component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Add a Simplorer/Twin Builder design and the Q3D dynamic component
tb = pyaedt.TwinBuilder(designname=tb_design_name)
-##########################################################
-# Add a Q3D dynamic component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Add a Q3D dynamic component
tb.add_q3d_dynamic_component(project_name,
q2d_design_name,
@@ -252,9 +219,7 @@
model_depth=lumped_length,
coupling_matrix_name="Original")
-##########################################################
-# Save project and release desktop
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and release desktop
tb.save_project()
tb.release_desktop(True, True)
diff --git a/examples/05-Q3D/Q2D_Example_CPWG.py b/examples/05-Q3D/Q2D_Example_CPWG.py
index c7f12e637f8..d5a6d5eb4c1 100644
--- a/examples/05-Q3D/Q2D_Example_CPWG.py
+++ b/examples/05-Q3D/Q2D_Example_CPWG.py
@@ -1,28 +1,25 @@
-"""
-2D Extractor: CPWG analysis
----------------------------
-This example shows how you can use PyAEDT to create a CPWG (coplanar waveguide with ground) design
-in 2D Extractor and run a simulation.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # 2D Extractor: CPWG analysis
+
+# This example shows how you can use PyAEDT to create a CPWG (coplanar waveguide with ground) design
+# in 2D Extractor and run a simulation.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
desktop_version = "2023.2"
-###############################################################################
-# Launch AEDT and 2D Extractor
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Launch AEDT and 2D Extractor
+#
# Launch AEDT 2023 R2 in graphical mode and launch 2D Extractor. This example
# uses SI units.
@@ -32,11 +29,11 @@
projectname=pyaedt.generate_unique_name("pyaedt_q2d_example"),
designname="coplanar_waveguide")
-###############################################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define variables.
+# +
e_factor = "e_factor"
sig_bot_w = "sig_bot_w"
co_gnd_w = "gnd_w"
@@ -60,10 +57,10 @@
sig_top_w = "({1}-{0}*2)".format(delta_w_half, sig_bot_w)
co_gnd_top_w = "({1}-{0}*2)".format(delta_w_half, co_gnd_w)
model_w = "{}*2+{}*2+{}".format(co_gnd_w, clearance, sig_bot_w)
+# -
-###############################################################################
-# Create primitives
-# ~~~~~~~~~~~~~~~~~
+# ## Create primitives
+#
# Create primitives and define the layer heights.
layer_1_lh = 0
@@ -71,9 +68,8 @@
layer_2_lh = layer_1_uh + "+" + d_h
layer_2_uh = layer_2_lh + "+" + cond_h
-###############################################################################
-# Create signal
-# ~~~~~~~~~~~~~
+# ## Create signal
+#
# Create a signal.
base_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_lh, 0], [sig_bot_w, layer_2_lh, 0]], name="signal")
@@ -82,11 +78,11 @@
q.modeler.connect([base_line_obj, top_line_obj])
q.modeler.move(objid=[base_line_obj], vector=["{}+{}".format(co_gnd_w, clearance), 0, 0])
-###############################################################################
-# Create coplanar ground
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coplanar ground
+#
# Create a coplanar ground.
+# +
base_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]],
name="co_gnd_left")
top_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]])
@@ -99,28 +95,27 @@
q.modeler.move(objid=[top_line_obj], vector=[delta_w_half, 0, 0])
q.modeler.connect([base_line_obj, top_line_obj])
q.modeler.move(objid=[base_line_obj], vector=["{}+{}*2+{}".format(co_gnd_w, clearance, sig_bot_w), 0, 0])
+# -
-###############################################################################
-# Create reference ground plane
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create reference ground plane
+#
# Create a reference ground plane.
q.modeler.create_rectangle(position=[0, layer_1_lh, 0], dimension_list=[model_w, cond_h], name="ref_gnd")
-###############################################################################
-# Create dielectric
-# ~~~~~~~~~~~~~~~~~
+# ## Create dielectric
+#
# Create a dielectric.
q.modeler.create_rectangle(
position=[0, layer_1_uh, 0], dimension_list=[model_w, d_h], name="Dielectric", matname="FR4_epoxy"
)
-###############################################################################
-# Create conformal coating
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create conformal coating
+#
# Create a conformal coating.
+# +
sm_obj_list = []
ids = [1,2,3]
if desktop_version >= "2023.1":
@@ -149,10 +144,10 @@
sm_obj.material_name = "SolderMask"
sm_obj.color = (0, 150, 100)
sm_obj.name = "solder_mask"
+# -
-###############################################################################
-# Assign conductor
-# ~~~~~~~~~~~~~~~~
+# ## Assign conductor
+#
# Assign a conductor to the signal.
obj = q.modeler.get_object_from_name("signal")
@@ -160,9 +155,8 @@
name=obj.name, target_objects=[obj], conductor_type="SignalLine", solve_option="SolveOnBoundary", unit="mm"
)
-###############################################################################
-# Create reference ground
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create reference ground
+#
# Create a reference ground.
obj = [q.modeler.get_object_from_name(i) for i in ["co_gnd_left", "co_gnd_right", "ref_gnd"]]
@@ -170,19 +164,18 @@
name="gnd", target_objects=obj, conductor_type="ReferenceGround", solve_option="SolveOnBoundary", unit="mm"
)
-###############################################################################
-# Assign Huray model on signal
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign Huray model on signal
+#
# Assign the Huray model on the signal.
obj = q.modeler.get_object_from_name("signal")
q.assign_huray_finitecond_to_edges(obj.edges, radius="0.5um", ratio=3, name="b_" + obj.name)
-###############################################################################
-# Create setup, analyze, and plot
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup, analyze, and plot
+#
# Create the setup, analyze it, and plot solution data.
-
+
+# +
setup = q.create_setup(setupname="new_setup")
sweep = setup.add_sweep(sweepname="sweep1", sweeptype="Discrete")
@@ -200,10 +193,10 @@
a = q.post.get_solution_data(expressions="Z0(signal,signal)", context="Original")
a.plot()
+# -
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
home = os.path.expanduser("~")
diff --git a/examples/05-Q3D/Q2D_Example_Stripline.py b/examples/05-Q3D/Q2D_Example_Stripline.py
index a36df6f8956..19f289b7600 100644
--- a/examples/05-Q3D/Q2D_Example_Stripline.py
+++ b/examples/05-Q3D/Q2D_Example_Stripline.py
@@ -1,29 +1,25 @@
-"""
-2D Extractor: stripline analysis
---------------------------------
-This example shows how you can use PyAEDT to create a differential stripline design in
-2D Extractor and run a simulation.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # 2D Extractor: stripline analysis
+
+# This example shows how you can use PyAEDT to create a differential stripline design in
+# 2D Extractor and run a simulation.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
project_path = pyaedt.generate_unique_project_name()
-###############################################################################
-# Launch AEDT and 2D Extractor
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and 2D Extractor
+#
# Launch AEDT 2023 R2 in graphical mode and launch 2D Extractor. This example
# uses SI units.
@@ -34,11 +30,11 @@
new_desktop_session=True
)
-###############################################################################
-# Define variables
-# ~~~~~~~~~~~~~~~~
+# ## Define variables
+#
# Define variables.
+# +
e_factor = "e_factor"
sig_w = "sig_bot_w"
sig_gap = "sig_gap"
@@ -65,10 +61,10 @@
sig_top_w = "({1}-{0}*2)".format(delta_w_half, sig_w)
co_gnd_top_w = "({1}-{0}*2)".format(delta_w_half, co_gnd_w)
model_w = "{}*2+{}*2+{}*2+{}".format(co_gnd_w, clearance, sig_w, sig_gap)
+# -
-###############################################################################
-# Create primitives
-# ~~~~~~~~~~~~~~~~~
+# ## Create primitives
+#
# Create primitives and define the layer heights.
layer_1_lh = 0
@@ -78,9 +74,8 @@
layer_3_lh = layer_2_uh + "+" + pp_h
layer_3_uh = layer_3_lh + "+" + cond_h
-###############################################################################
-# Create positive signal
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create positive signal
+#
# Create a positive signal.
base_line_obj = q.modeler.create_polyline([[0, layer_2_lh, 0], [sig_w, layer_2_lh, 0]], name="signal_p")
@@ -89,8 +84,8 @@
q.modeler.connect([base_line_obj, top_line_obj])
q.modeler.move([base_line_obj], ["{}+{}".format(co_gnd_w, clearance), 0, 0])
-# Create negative signal
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create negative signal
+#
# Create a negative signal.
base_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_lh, 0], [sig_w, layer_2_lh, 0]], name="signal_n")
@@ -99,11 +94,11 @@
q.modeler.connect([base_line_obj, top_line_obj])
q.modeler.move(objid=[base_line_obj], vector=["{}+{}+{}+{}".format(co_gnd_w, clearance, sig_w, sig_gap), 0, 0])
-###############################################################################
-# Create coplanar ground
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coplanar ground
+#
# Create a coplanar ground.
+# +
base_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]],
name="co_gnd_left")
top_line_obj = q.modeler.create_polyline(position_list=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]])
@@ -117,18 +112,17 @@
q.modeler.connect([base_line_obj, top_line_obj])
q.modeler.move(objid=[base_line_obj],
vector=["{}+{}*2+{}*2+{}".format(co_gnd_w, clearance, sig_w, sig_gap), 0, 0])
+# -
-###############################################################################
-# Create reference ground plane
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create reference ground plane
+#
# Create a reference ground plane.
q.modeler.create_rectangle(position=[0, layer_1_lh, 0], dimension_list=[model_w, cond_h], name="ref_gnd_u")
q.modeler.create_rectangle(position=[0, layer_3_lh, 0], dimension_list=[model_w, cond_h], name="ref_gnd_l")
-###############################################################################
-# Create dielectric
-# ~~~~~~~~~~~~~~~~~
+# ## Create dielectric
+#
# Create a dielectric.
q.modeler.create_rectangle(
@@ -141,11 +135,11 @@
position=[0, layer_2_lh, 0], dimension_list=[model_w, cond_h], name="Filling", matname="FR4_epoxy"
)
-###############################################################################
-# Assign conductors
-# ~~~~~~~~~~~~~~~~~
+# ## Assign conductors
+#
# Assign conductors to the signal.
+# +
obj = q.modeler.get_object_from_name("signal_p")
q.assign_single_conductor(
name=obj.name, target_objects=[obj], conductor_type="SignalLine", solve_option="SolveOnBoundary", unit="mm"
@@ -155,10 +149,10 @@
q.assign_single_conductor(
name=obj.name, target_objects=[obj], conductor_type="SignalLine", solve_option="SolveOnBoundary", unit="mm"
)
+# -
-###############################################################################
-# Create reference ground
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create reference ground
+#
# Create a reference ground.
obj = [q.modeler.get_object_from_name(i) for i in ["co_gnd_left", "co_gnd_right", "ref_gnd_u", "ref_gnd_l"]]
@@ -166,34 +160,35 @@
name="gnd", target_objects=obj, conductor_type="ReferenceGround", solve_option="SolveOnBoundary", unit="mm"
)
-###############################################################################
-# Assign Huray model on signals
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign Huray model on signals
+#
# Assign the Huray model on the signals.
+# +
obj = q.modeler.get_object_from_name("signal_p")
q.assign_huray_finitecond_to_edges(obj.edges, radius="0.5um", ratio=3, name="b_" + obj.name)
obj = q.modeler.get_object_from_name("signal_n")
q.assign_huray_finitecond_to_edges(obj.edges, radius="0.5um", ratio=3, name="b_" + obj.name)
+# -
-###############################################################################
-# Define differential pair
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define differential pair
+#
# Define the differential pair.
matrix = q.insert_reduced_matrix(operation_name=q.MATRIXOPERATIONS.DiffPair, source_names=["signal_p", "signal_n"],
rm_name="diff_pair")
-###############################################################################
-# Create setup, analyze, and plot
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup, analyze, and plot
+#
# Create a setup, analyze, and plot solution data.
# Create a setup.
+
setup = q.create_setup(setupname="new_setup")
# Add a sweep.
+
sweep = setup.add_sweep(sweepname="sweep1", sweeptype="Discrete")
sweep.props["RangeType"] = "LinearStep"
sweep.props["RangeStart"] = "1GHz"
@@ -205,21 +200,23 @@
sweep.update()
# Analyze the nominal design and plot characteristic impedance.
+
q.analyze()
plot_sources = matrix.get_sources_for_plot(category="Z0")
a = q.post.get_solution_data(expressions=plot_sources, context=matrix.name)
a.plot(snapshot_path=os.path.join(q.working_directory, "plot.jpg")) # Save plot as jpg
# Add a parametric sweep and analyze.
+
parametric = q.parametrics.add(sweep_var="sig_bot_w", start_point=75, end_point=100, step=5,
variation_type="LinearStep")
parametric.add_variation(sweep_var="sig_gap", start_point="100um", end_point="200um", step=5,
variation_type="LinearCount")
q.analyze_setup(name=parametric.name)
-###############################################################################
-# Save project and release AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and release AEDT
+#
# Save the project and release AEDT.
+
q.save_project()
q.release_desktop()
diff --git a/examples/05-Q3D/Q3D_DC_IR.py b/examples/05-Q3D/Q3D_DC_IR.py
index 976279b53c4..6af3dddbd3d 100644
--- a/examples/05-Q3D/Q3D_DC_IR.py
+++ b/examples/05-Q3D/Q3D_DC_IR.py
@@ -1,22 +1,19 @@
-"""
-Q3D Extractor: PCB DCIR analysis
---------------------------------
-This example shows how you can use PyAEDT to create a design in
-Q3D Extractor and run a DC IR Drop simulation starting from an EDB Project.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Q3D Extractor: PCB DCIR analysis
+#
+# This example shows how you can use PyAEDT to create a design in
+# Q3D Extractor and run a DC IR Drop simulation starting from an EDB Project.
+
+# ## Perform required imports
+#
# Perform required imports.
+
import os
import pyaedt
-
-###############################################################################
-# Set up project files and path
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set up project files and path
+#
# Download needed project file and set up temporary project directory.
+
project_dir = pyaedt.generate_unique_folder_name()
aedb_project = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=project_dir)
coil = pyaedt.downloads.download_file('inductance_3d_component', 'air_coil.a3dcomp')
@@ -25,12 +22,11 @@
output_edb = os.path.join(project_dir, project_name + '.aedb')
output_q3d = os.path.join(project_dir, project_name + '_q3d.aedt')
-
-###############################################################################
-# Open EDB
-# ~~~~~~~~
+# ## Open EDB
+#
# Open the EDB project and create a cutout on the selected nets
# before exporting to Q3D.
+
edb = pyaedt.Edb(aedb_project, edbversion="2023.2")
edb.cutout(["1.2V_AVDLL_PLL", "1.2V_AVDDL", "1.2V_DVDDL", "NetR106_1"],
["GND"],
@@ -38,10 +34,8 @@
use_pyaedt_extent_computing=True,
)
-
-###############################################################################
-# Identify pin positions
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Identify pin positions
+#
# Identify [x,y] pin locations on the components to define where to assign sources
# and sinks for Q3D.
@@ -50,11 +44,11 @@
pin_u9_2 = [i for i in edb.components["U9"].pins.values() if i.net_name == "1.2V_DVDDL"]
pin_u11_r106 = [i for i in edb.components["U11"].pins.values() if i.net_name == "NetR106_1"]
-###############################################################################
-# Append Z Positions
-# ~~~~~~~~~~~~~~~~~~
+# ## Append Z Positions
+#
# Compute Q3D 3D position. The factor 1000 converts from "meters" to "mm".
+# +
location_u11_scl = [i * 1000 for i in pin_u11_scl[0].position]
location_u11_scl.append(edb.components["U11"].upper_elevation * 1000)
@@ -66,12 +60,13 @@
location_u11_r106 = [i * 1000 for i in pin_u11_r106[0].position]
location_u11_r106.append(edb.components["U11"].upper_elevation * 1000)
+# -
-###############################################################################
-# Identify pin positions for 3D components
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Identify pin positions for 3D components
+#
# Identify the pin positions where 3D components of passives are to be added.
+# +
location_l2_1 = [i * 1000 for i in edb.components["L2"].pins["1"].position]
location_l2_1.append(edb.components["L2"].upper_elevation * 1000)
location_l4_1 = [i * 1000 for i in edb.components["L4"].pins["1"].position]
@@ -79,43 +74,41 @@
location_r106_1 = [i * 1000 for i in edb.components["R106"].pins["1"].position]
location_r106_1.append(edb.components["R106"].upper_elevation * 1000)
+# -
-###############################################################################
-# Save and close EDB
-# ~~~~~~~~~~~~~~~~~~
+# ## Save and close EDB
+#
# Save and close EDB. Then, open EDT in HFSS 3D Layout to generate the 3D model.
+# +
edb.save_edb()
edb.close_edb()
h3d = pyaedt.Hfss3dLayout(output_edb, specified_version="2023.2", non_graphical=False, new_desktop_session=True)
+# -
-###############################################################################
-# Export to Q3D
-# ~~~~~~~~~~~~~
+# ## Export to Q3D
+#
# Create a dummy setup and export the layout in Q3D.
# The ``keep_net_name`` parameter reassigns Q3D net names from HFSS 3D Layout.
+
setup = h3d.create_setup()
setup.export_to_q3d(output_q3d, keep_net_name=True)
h3d.close_project()
-
-
-###############################################################################
-# Open Q3D
-# ~~~~~~~~
+# ## Open Q3D
+#
# Launch the newly created q3d project.
q3d = pyaedt.Q3d(output_q3d)
q3d.modeler.delete("GND")
q3d.delete_all_nets()
-
-###############################################################################
-# Insert inductors
-# ~~~~~~~~~~~~~~~~
+# ## Insert inductors
+#
# Create new coordinate systems and place 3D component inductors.
+# +
q3d.modeler.create_coordinate_system(location_l2_1, name="L2")
comp = q3d.modeler.insert_3d_component(coil, targetCS="L2")
comp.rotate(q3d.AXIS.Z, -90)
@@ -135,12 +128,13 @@
comp3.rotate(q3d.AXIS.Z, -90)
q3d.modeler.set_working_coordinate_system("Global")
+# -
-###############################################################################
-# Delete dielectrics
-# ~~~~~~~~~~~~~~~~~~
+# ## Delete dielectrics
+#
# Delete all dielectric objects since not needed in DC analysis.
+# +
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4"))
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4_2"))
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4_3"))
@@ -150,13 +144,14 @@
objs_copper_names = [i.name for i in objs_copper]
q3d.plot(show=False,objects=objs_copper_names, plot_as_separate_objects=False,
export_path=os.path.join(q3d.working_directory, "Q3D.jpg"), plot_air_objects=False)
+# -
-###############################################################################
-# Assign source and sink
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Use previously calculated positions to identify faces,
-# select the net "1_Top" and
+# ## Assign source and sink
+#
+# Use previously calculated positions to identify faces, select the net "1_Top" and
# assign sources and sinks on nets.
+
+# +
sink_f = q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_scl, 0.1)
source_f1 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_1_scl, 0.1)
source_f2 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_2_scl, 0.1)
@@ -177,10 +172,10 @@
q3d.edit_sources(dcrl={"{}:{}".format(source1.props["Net"], source1.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source2.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source3.name): "-1.0A"})
+# -
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup and a frequency sweep from DC to 2GHz.
# Analyze project.
@@ -192,9 +187,8 @@
setup.props["DC"]["Cond"]["MaxPass"]=3
setup.analyze()
-###############################################################################
-# Field Calculator
-# ~~~~~~~~~~~~~~~~
+# ## Field Calculator
+#
# We will create a named expression using field calculator.
drop_name = "Vdrop3_3"
@@ -205,11 +199,11 @@
q3d.ofieldsreporter.CalcOp("+")
q3d.ofieldsreporter.AddNamedExpression(drop_name, "DC R/L Fields")
-###############################################################################
-# Phi plot
-# ~~~~~~~~
+# ## Phi plot
+#
# Compute ACL solutions and plot them.
+# +
plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), quantityName=drop_name,
intrinsincDict={"Freq": "1GHz"})
@@ -223,14 +217,15 @@
plot_cad_objs=False,
log_scale=False,
)
+# -
-###############################################################################
-# Computing Voltage on Source Circles
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Computing Voltage on Source Circles
+#
# Using Field Calculator we can compute the voltage on source circles and get the value
# using get_solution_data method.
+# +
curves = []
for source_circle, source_bound in zip(sources_objs, sources_bounds):
source_sheet_name = source_circle.name
@@ -243,7 +238,6 @@
q3d.ofieldsreporter.CalcOp("Maximum")
q3d.ofieldsreporter.AddNamedExpression("V{}".format(source_bound.name), "DC R/L Fields")
-
data = q3d.post.get_solution_data(
curves,
q3d.nominal_adaptive,
@@ -252,12 +246,12 @@
)
for curve in curves:
print(data.data_real(curve))
+# -
-
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# ``release_desktop`` method. All methods provide for saving projects before closing.
+
q3d.save_project()
q3d.release_desktop()
diff --git a/examples/05-Q3D/Q3D_Example.py b/examples/05-Q3D/Q3D_Example.py
index 2bf882c57f0..cee6f9398ab 100644
--- a/examples/05-Q3D/Q3D_Example.py
+++ b/examples/05-Q3D/Q3D_Example.py
@@ -1,28 +1,24 @@
-"""
-Q3D Extractor: busbar analysis
-------------------------------
-This example shows how you can use PyAEDT to create a busbar design in
-Q3D Extractor and run a simulation.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Q3D Extractor: busbar analysis
+
+# This example shows how you can use PyAEDT to create a busbar design in
+# Q3D Extractor and run a simulation.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Set debugger mode
-# ~~~~~~~~~~~~~~~~~
+# ## Set debugger mode
+#
# PyAEDT allows to enable a debug logger which logs all methods called and argument passed.
# This example shows how to enable it.
@@ -30,10 +26,8 @@
pyaedt.settings.enable_debug_methods_argument_logger = True
pyaedt.settings.enable_debug_internal_methods_logger = False
-
-###############################################################################
-# Launch AEDT and Q3D Extractor
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and Q3D Extractor
+#
# Launch AEDT 2023 R2 in graphical mode and launch Q3D Extractor. This example uses SI units.
q = pyaedt.Q3d(projectname=pyaedt.generate_unique_project_name(),
@@ -41,11 +35,11 @@
non_graphical=non_graphical,
new_desktop_session=True)
-###############################################################################
-# Create primitives
-# ~~~~~~~~~~~~~~~~~
+# ## Create primitives
+#
# Create polylines for three busbars and a box for the substrate.
+# +
b1 = q.modeler.create_polyline(
[[0, 0, 0], [-100, 0, 0]],
name="Bar1",
@@ -81,13 +75,14 @@
q.modeler["substrate"].transparency = 0.8
q.plot(show=False, export_path=os.path.join(q.working_directory, "Q3D.jpg"), plot_air_objects=False)
+# -
-###############################################################################
-# Set up boundaries
-# ~~~~~~~~~~~~~~~~~
+# ## Set up boundaries
+#
# Identify nets and assign sources and sinks to all nets.
# There is a source and sink for each busbar.
+# +
q.auto_identify_nets()
q.source("Bar1", axisdir=q.AxisDir.XPos, name="Source1")
@@ -98,10 +93,10 @@
q.source("Bar3", axisdir=q.AxisDir.XPos, name="Source3")
bar3_sink = q.sink("Bar3", axisdir=q.AxisDir.YPos)
bar3_sink.name = "Sink3"
+# -
-###############################################################################
-# Print information
-# ~~~~~~~~~~~~~~~~~
+# ## Print information
+#
# Use the different methods available to print net and terminal information.
print(q.nets)
@@ -112,9 +107,8 @@
print(q.net_sources("Bar2"))
print(q.net_sources("Bar3"))
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup for Q3D Extractor and add a sweep that defines the adaptive
# frequency value.
@@ -125,9 +119,8 @@
sw1.props["RangeStep"] = "5MHz"
sw1.update()
-###############################################################################
-# Get curves to plot
-# ~~~~~~~~~~~~~~~~~~
+# ## Get curves to plot
+#
# Get the curves to plot. The following code simplifies the way to get curves.
data_plot_self = q.matrices[0].get_sources_for_plot(get_self_terms=True, get_mutual_terms=False)
@@ -135,25 +128,22 @@
data_plot_self
data_plot_mutual
-###############################################################################
-# Create rectangular plot
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create rectangular plot
+#
# Create a rectangular plot and a data table.
q.post.create_report(expressions=data_plot_self)
q.post.create_report(expressions=data_plot_mutual, context="Original", plot_type="Data Table")
-###############################################################################
-# Solve setup
-# ~~~~~~~~~~~
+# ## Solve setup
+#
# Solve the setup.
q.analyze()
q.save_project()
-###############################################################################
-# Get report data
-# ~~~~~~~~~~~~~~~
+# ## Get report data
+#
# Get the report data into a data structure that allows you to manipulate it.
a = q.post.get_solution_data(expressions=data_plot_self, context="Original")
@@ -161,11 +151,11 @@
a.data_magnitude()
a.plot()
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# ``release_desktop`` method. All methods provide for saving projects before closing.
+
pyaedt.settings.enable_debug_logger = False
pyaedt.settings.enable_debug_methods_argument_logger = False
q.release_desktop(close_projects=True, close_desktop=True)
diff --git a/examples/05-Q3D/Q3D_from_EDB.py b/examples/05-Q3D/Q3D_from_EDB.py
index a104684b832..fe4c8d8b3a8 100644
--- a/examples/05-Q3D/Q3D_from_EDB.py
+++ b/examples/05-Q3D/Q3D_from_EDB.py
@@ -1,43 +1,40 @@
-"""
-Q3D Extractor: PCB analysis
----------------------------
-This example shows how you can use PyAEDT to create a design in
-Q3D Extractor and run a simulation starting from an EDB Project.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Q3D Extractor: PCB analysis
+
+# This example shows how you can use PyAEDT to create a design in
+# Q3D Extractor and run a simulation starting from an EDB Project.
+
+# ## Perform required imports
+#
# Perform required imports.
+
import os
import pyaedt
-
-###############################################################################
-# Setup project files and path
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Setup project files and path
+#
# Download of needed project file and setup of temporary project directory.
+
+# +
project_dir = pyaedt.generate_unique_folder_name()
aedb_project = pyaedt.downloads.download_file('edb/ANSYS-HSD_V1.aedb',destination=project_dir)
project_name = pyaedt.generate_unique_name("HSD")
output_edb = os.path.join(project_dir, project_name + '.aedb')
output_q3d = os.path.join(project_dir, project_name + '_q3d.aedt')
+# -
-
-###############################################################################
-# Open EDB
-# ~~~~~~~~
+# ## Open EDB
+#
# Open the edb project and created a cutout on the selected nets
# before exporting to Q3D.
+
edb = pyaedt.Edb(aedb_project, edbversion="2023.2")
edb.cutout(["CLOCK_I2C_SCL", "CLOCK_I2C_SDA"], ["GND"], output_aedb_path=output_edb,
use_pyaedt_extent_computing=True, )
-###############################################################################
-# Identify pins position
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Identify pins position
+#
# Identify [x,y] pin locations on the components to define where to assign sources
# and sinks for Q3D and append Z elevation.
@@ -47,11 +44,11 @@
pin_u1_sda = [i for i in edb.components["U1"].pins.values() if i.net_name == "CLOCK_I2C_SDA"]
-###############################################################################
-# Append Z Positions
-# ~~~~~~~~~~~~~~~~~~
+# ## Append Z Positions
+#
# Note: The factor 100 converts from "meters" to "mm"
+# +
location_u13_scl = [i * 1000 for i in pin_u13_scl[0].position]
location_u13_scl.append(edb.components["U13"].upper_elevation * 1000)
@@ -63,45 +60,41 @@
location_u1_sda = [i * 1000 for i in pin_u1_sda[0].position]
location_u1_sda.append(edb.components["U1"].upper_elevation * 1000)
+# -
-###############################################################################
-# Save and close Edb
-# ~~~~~~~~~~~~~~~~~~
+# ## Save and close Edb
+#
# Save, close Edb and open it in Hfss 3D Layout to generate the 3D model.
+# +
edb.save_edb()
edb.close_edb()
h3d = pyaedt.Hfss3dLayout(output_edb, specified_version="2023.2", non_graphical=True, new_desktop_session=True)
+# -
-###############################################################################
-# Export to Q3D
-# ~~~~~~~~~~~~~
+# ## Export to Q3D
+#
# Create a dummy setup and export the layout in Q3D.
# keep_net_name will reassign Q3D nets names from Hfss 3D Layout.
+
setup = h3d.create_setup()
setup.export_to_q3d(output_q3d, keep_net_name=True)
h3d.close_project()
-
-
-###############################################################################
-# Open Q3D
-# ~~~~~~~~
+# ## Open Q3D
+#
# Launch the newly created q3d project and plot it.
q3d = pyaedt.Q3d(output_q3d)
q3d.plot(show=False, objects=["CLOCK_I2C_SCL", "CLOCK_I2C_SDA"],
export_path=os.path.join(q3d.working_directory, "Q3D.jpg"), plot_air_objects=False)
-###############################################################################
-# Assign Source and Sink
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Assign Source and Sink
+#
# Use previously calculated position to identify faces and
# assign sources and sinks on nets.
-
-
f1 = q3d.modeler.get_faceid_from_position(location_u13_scl, obj_name="CLOCK_I2C_SCL")
q3d.source(f1, net_name="CLOCK_I2C_SCL")
f1 = q3d.modeler.get_faceid_from_position(location_u13_sda, obj_name="CLOCK_I2C_SDA")
@@ -111,9 +104,8 @@
f1 = q3d.modeler.get_faceid_from_position(location_u1_sda, obj_name="CLOCK_I2C_SDA")
q3d.sink(f1, net_name="CLOCK_I2C_SDA")
-###############################################################################
-# Create Setup
-# ~~~~~~~~~~~~
+# ## Create Setup
+#
# Create a setup and a frequency sweep from DC to 2GHz.
# Analyze project.
@@ -124,27 +116,25 @@
sweep.add_subrange("LinearStep", 0, end=2, count=0.05, unit="GHz", save_single_fields=False, clear=True)
setup.analyze()
-###############################################################################
-# ACL Report
-# ~~~~~~~~~~
+# ## ACL Report
+#
# Compute ACL solutions and plot them.
traces_acl = q3d.post.available_report_quantities(quantities_category="ACL Matrix")
solution = q3d.post.get_solution_data(traces_acl)
solution.plot()
-###############################################################################
-# ACR Report
-# ~~~~~~~~~~
+# ## ACR Report
+#
# Compute ACR solutions and plot them.
traces_acr = q3d.post.available_report_quantities(quantities_category="ACR Matrix")
solution2 = q3d.post.get_solution_data(traces_acr)
solution2.plot()
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# ``release_desktop`` method. All methods provide for saving projects before closing.
+
q3d.release_desktop()
diff --git a/examples/05-Q3D/Readme.txt b/examples/05-Q3D/index.rst
similarity index 61%
rename from examples/05-Q3D/Readme.txt
rename to examples/05-Q3D/index.rst
index 1d4f3398872..d49937f7529 100644
--- a/examples/05-Q3D/Readme.txt
+++ b/examples/05-Q3D/index.rst
@@ -3,3 +3,11 @@
These examples use PyAEDT to show some end-to-end workflows for 2D Extractor and
Q3D Extractor. This includes model generation, setup, and thermal postprocessing.
+.. nbgallery::
+
+ Q2D_Armoured_Cable.py
+ Q2D_Example_CPWG.py
+ Q2D_Example_Stripline.py
+ Q3D_DC_IR.py
+ Q3D_Example.py
+ Q3D_from_EDB.py
\ No newline at end of file
diff --git a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py b/examples/06-Multiphysics/Hfss_Icepak_Coupling.py
index 3d392b39d61..79c943db216 100644
--- a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py
+++ b/examples/06-Multiphysics/Hfss_Icepak_Coupling.py
@@ -1,73 +1,62 @@
-"""
-Multiphysics: HFSS-Icepak multiphysics analysis
-------------------------------------------------
-This example shows how you can create a project from scratch in HFSS and Icepak (linked to HFSS).
-This includes creating a setup, solving it, and creating postprocessing outputs.
-
-To provide the advanced postprocessing features needed for this example, the ``numpy``,
-``matplotlib``, and ``pyvista`` packages must be installed on the machine.
-
-This examples runs only on Windows using CPython.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Multiphysics: HFSS-Icepak multiphysics analysis
+#
+# This example shows how you can create a project from scratch in HFSS and Icepak (linked to HFSS).
+# This includes creating a setup, solving it, and creating postprocessing outputs.
+#
+# To provide the advanced postprocessing features needed for this example, the ``numpy``,
+# ``matplotlib``, and ``pyvista`` packages must be installed on the machine.
+#
+# This examples runs only on Windows using CPython.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
from pyaedt.generic.pdf import AnsysReport
+import tempfile
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Setup
+#
# Set non-graphical mode.
-# You can set ``non_graphical`` either to ``True`` or ``False``.
+# Set ``non_graphical`` to ``False`` if the AEDT user interface should
+# be started when HFSS and Icepak are accessed.
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
non_graphical = False
desktopVersion = "2023.2"
-###############################################################################
-# Open project
-# ~~~~~~~~~~~~
-# Open the project.
-
-NewThread = True
-
-project_file = pyaedt.generate_unique_project_name()
-
-###############################################################################
-# Launch AEDT and initialize HFSS
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and initialize HFSS
+#
# Launch AEDT and initialize HFSS. If there is an active HFSS design, the ``aedtapp``
# object is linked to it. Otherwise, a new design is created.
-aedtapp = pyaedt.Hfss(projectname=project_file,
+aedtapp = pyaedt.Hfss(projectname=os.path.join(temp_dir.name, "Icepak_HFSS_Coupling"),
+ designname="RF",
specified_version=desktopVersion,
non_graphical=non_graphical,
- new_desktop_session=NewThread
+ new_desktop_session=True
)
-###############################################################################
-# Initialize variable settings
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Initialize variable settings. You can initialize a variable simply by creating
-# it as a list object. If you enter the prefix ``$``, the variable is created for
-# the project. Otherwise, the variable is created for the design.
+# ## Parameters
+#
+# Parameters can be instantiated by defining them as a key used for the application
+# instance as demonstrated below. The prefix ``$`` is used to define
+# project-wide scope for the parameter. Otherwise the parameter scope is limited the current design.
-aedtapp["$coax_dimension"] = "100mm"
+aedtapp["$coax_dimension"] = "100mm" # Project-wide scope.
udp = aedtapp.modeler.Position(0, 0, 0)
-aedtapp["inner"] = "3mm"
+aedtapp["inner"] = "3mm" # Local "Design" scope.
-###############################################################################
-# Create coaxial and cylinders
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create coaxial and cylinders
+#
# Create a coaxial and three cylinders. You can apply parameters
-# directly using the :func:`pyaedt.modeler.Primitives3D.Primitives3D.create_cylinder`
+# directly using the `pyaedt.modeler.Primitives3D.Primitives3D.create_cylinder`
# method. You can assign a material directly to the object creation action.
-# Optionally, you can assign a material using the :func:`assign_material` method.
+# Optionally, you can assign a material using the `assign_material` method.
-# TODO: How does this work when two truesurfaces are defined?
+# TODO: How does this work when two true surfaces are defined?
o1 = aedtapp.modeler.create_cylinder(cs_axis=aedtapp.PLANE.ZX, position=udp, radius="inner", height="$coax_dimension",
numSides=0, name="inner")
o2 = aedtapp.modeler.create_cylinder(cs_axis=aedtapp.PLANE.ZX, position=udp, radius=8, height="$coax_dimension",
@@ -75,9 +64,8 @@
o3 = aedtapp.modeler.create_cylinder(cs_axis=aedtapp.PLANE.ZX, position=udp, radius=10, height="$coax_dimension",
numSides=0, name="outer")
-###############################################################################
-# Assign colors
-# ~~~~~~~~~~~~~
+# ## Assign colors
+#
# Assign colors to each primitive.
o1.color = (255, 0, 0)
@@ -86,49 +74,50 @@
o3.transparency = 0.8
aedtapp.modeler.fit_all()
-###############################################################################
-# Assign materials
-# ~~~~~~~~~~~~~~~~
+# ## Assign materials
+#
# Assign materials. You can assign materials either directly when creating the primitive,
# which was done for ``id2``, or after the object is created.
o1.material_name = "Copper"
o3.material_name = "Copper"
-###############################################################################
-# Perform modeler operations
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform modeler operations
+#
# Perform modeler operations. You can subtract, add, and perform other operations
# using either the object ID or object name.
aedtapp.modeler.subtract(o3, o2, True)
aedtapp.modeler.subtract(o2, o1, True)
-###############################################################################
-# Perform mesh operations
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Perform mesh operations. Most mesh operations are available.
-# After a mesh is created, you can access a mesh operation to
-# edit or review parameter values.
+# ## Assign Mesh Operations
+#
+# Most mesh operations are accessible using the ``mesh`` property
+# which is an instance of the ``pyaedt.modules.MeshIcepak.IcepakMesh`` class.
+#
+# This example demonstrates the use of several common mesh
+# operatons.
aedtapp.mesh.assign_initial_mesh_from_slider(level=6)
aedtapp.mesh.assign_model_resolution(names=[o1.name, o3.name], defeature_length=None)
aedtapp.mesh.assign_length_mesh(names=o2.faces, isinside=False, maxlength=1, maxel=2000)
-###############################################################################
-# Create excitations
-# ~~~~~~~~~~~~~~~~~~
-# Create excitations. The ``create_wave_port_between_objects`` method automatically
-# identifies the closest faces on a predefined direction and creates a sheet to cover
-# the faces. It also assigns a port to this face. If ``add_pec_cap=True``, the method
-# creates a PEC cap.
+# ## Create HFSS Sources
+#
+# The RF power dissipated in the HFSS model will act as the thermal
+# source for in Icepak. The ``create_wave_port_between_objects`` method
+# s used to assign the RF ports that inject RF power into the HFSS
+# model. If the parameter ``add_pec_cap=True``, then the method
+# creates a perfectly conducting (lossless) cap covering the port.
+# +
aedtapp.wave_port(signal="inner",
reference="outer",
integration_line=1,
create_port_sheet=True,
create_pec_cap=True,
name="P1")
+
aedtapp.wave_port(signal="inner",
reference="outer",
integration_line=4,
@@ -138,10 +127,10 @@
port_names = aedtapp.get_all_sources()
aedtapp.modeler.fit_all()
+# -
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## HFSS Simulation Setup
+#
# Create a setup. A setup is created with default values. After its creation,
# you can change values and update the setup. The ``update`` method returns a Boolean
# value.
@@ -152,55 +141,69 @@
setup.props["BasisOrder"] = 2
setup.props["MaximumPasses"] = 1
-###############################################################################
-# Create sweep
-# ~~~~~~~~~~~~
-# Create a sweep. A sweep is created with default values.
+# ## HFSS Frequency Sweep
+#
+# The frequency sweep defines the RF frequency range over which the RF power is
+# injected into the structure.
sweepname = aedtapp.create_linear_count_sweep(setupname="MySetup", unit="GHz", freqstart=0.8, freqstop=1.2,
num_of_freq_points=401, sweep_type="Interpolating")
-################################################################################
-# Create Icepak model
-# ~~~~~~~~~~~~~~~~~~~
-# Create an Icepak model. After an HFSS setup is ready, link this model to an Icepak
-# project and run a coupled physics analysis. The :func:`FieldAnalysis3D.copy_solid_bodies_from`
-# method imports a model from HFSS with all material settings.
+# ## Create Icepak model
+#
+# After an HFSS setup has been defined, the model can be lnked to an Icepak
+# design and the coupled physics analysis can be run. The `FieldAnalysis3D.copy_solid_bodies_from()`
+# method imports a model from HFSS into Icepak including all material definitions.
-ipkapp = pyaedt.Icepak()
+ipkapp = pyaedt.Icepak(designname="CalcTemp")
ipkapp.copy_solid_bodies_from(aedtapp)
-################################################################################
-# Link sources to EM losses
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
-# Link sources to the EM losses.
+# ## Link RF Thermal Source
+#
+# The RF loss in HFSS will be used as the thermal source in Icepak.
surfaceobj = ["inner", "outer"]
-ipkapp.assign_em_losses(designname=aedtapp.design_name, setupname="MySetup", sweepname="LastAdaptive",
- map_frequency="1GHz", surface_objects=surfaceobj, paramlist=["$coax_dimension", "inner"])
+ipkapp.assign_em_losses(designname=aedtapp.design_name, setupname="MySetup",
+ sweepname="LastAdaptive",
+ map_frequency="1GHz",
+ surface_objects=surfaceobj,
+ paramlist=["$coax_dimension", "inner"])
-#################################################################################
-# Edit gravity setting
-# ~~~~~~~~~~~~~~~~~~~~
-# Edit the gravity setting if necessary because it is important for a fluid analysis.
+# ## Assign the Direction of Gravity
+#
+# Set the direction of gravity for convection in Icepak. Gravity drives a temperature gradient
+# due to the dependence of gas density on temperature.
ipkapp.edit_design_settings(aedtapp.GRAVITY.ZNeg)
-################################################################################
-# Set up Icepak project
-# ~~~~~~~~~~~~~~~~~~~~~
-# Set up the Icepak project. When you create a setup, default settings are applied.
-# When you need to change a property of the setup, you can use the ``props``
-# command to pass the correct value to the property. The ``update`` function
+# ## Set up the Icepak Project
+#
+# The initial solution setup applies default values that can subsequently
+# be modified as shown here.
+# The ``props`` property enables access to all solution settings.
+#
+# The ``update`` function
# applies the settings to the setup. The setup creation process is identical
# for all tools.
setup_ipk = ipkapp.create_setup("SetupIPK")
setup_ipk.props["Convergence Criteria - Max Iterations"] = 3
-################################################################################
-# Edit or review mesh parameters
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Icepak Solution Properteis
+#
+# The setup properties are accessible through the ``props`` property as
+# an ordered dict. The ``keys()`` method can be used to retrieve all settings for
+# the setup.
+#
+# Find propertes that contain the string ``"Convergence"`` and print the default values.
+
+conv_props = [k for k in setup_ipk.props.keys() if "Convergence" in k]
+print("Here are some default setup properties:")
+for p in conv_props:
+ print("\"" + p + "\" -> " + str(setup_ipk.props[p]))
+
+# ### Edit or Review Mesh Parameters
+#
# Edit or review the mesh parameters. After a mesh is created, you can access
# a mesh operation to edit or review parameter values.
@@ -209,43 +212,44 @@
airfaces = ipkapp.modeler.get_object_faces(airbox)
ipkapp.assign_openings(airfaces)
-################################################################################
-# Close and open projects
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Close and open projects
+#
# Close and open the projects to ensure that the HFSS - Icepak coupling works
# correctly in AEDT versions 2019 R3 through 2021 R1. Closing and opening projects
# can be helpful when performing operations on multiple projects.
aedtapp.save_project()
+project_filename = aedtapp.project_file # Save the project file name.
aedtapp.close_project(aedtapp.project_name)
-aedtapp = pyaedt.Hfss(project_file)
+aedtapp = pyaedt.Hfss(project_filename)
ipkapp = pyaedt.Icepak()
ipkapp.solution_type = ipkapp.SOLUTIONS.Icepak.SteadyTemperatureAndFlow
ipkapp.modeler.fit_all()
-################################################################################
-# Solve Icepak project
-# ~~~~~~~~~~~~~~~~~~~~
-# Solve the Icepak project and the HFSS sweep.
+# ## Solve the Project
+#
+# Solve the Icepak and HFSS models.
-setup1 = ipkapp.analyze_setup("SetupIPK")
+ipkapp.setups[0].analyze() # Run the Icepak analysis.
aedtapp.save_project()
aedtapp.modeler.fit_all()
-aedtapp.analyze_setup("MySetup")
+aedtapp.setups[0].analyze() # Run the HFSS analysis.
-################################################################################
-# Generate field plots and export
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ### Plot and Export Results
+#
# Generate field plots on the HFSS project and export them as images.
+# +
cutlist = [pyaedt.constants.GLOBALCS.XY, pyaedt.constants.GLOBALCS.ZX, pyaedt.constants.GLOBALCS.YZ]
vollist = [o2.name]
-setup_name = "MySetup : LastAdaptive"
-quantity_name = "ComplexMag_E"
+quantity_name1 = "ComplexMag_E"
quantity_name2 = "ComplexMag_H"
-intrinsic = {"Freq": "1GHz", "Phase": "0deg"}
+intrinsic = {"Freq": aedtapp.setups[0].props["Frequency"],
+ "Phase": "0deg"}
surflist = aedtapp.modeler.get_object_faces("outer")
-plot1 = aedtapp.post.create_fieldplot_surface(surflist, quantity_name2, setup_name, intrinsic)
+plot1 = aedtapp.post.create_fieldplot_surface(surflist, quantity_name2,
+ setup_name=aedtapp.nominal_adaptive,
+ intrinsicDict=intrinsic)
results_folder = os.path.join(aedtapp.working_directory, "Coaxial_Results_NG")
if not os.path.exists(results_folder):
@@ -261,27 +265,28 @@
plot_cad_objs=False,
log_scale=False,
)
+# -
-################################################################################
-# Generate animation from field plots
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate animation from field plots
+#
# Generate an animation from field plots using PyVista.
+# +
import time
start = time.time()
cutlist = ["Global:XY"]
-phases = [str(i * 5) + "deg" for i in range(18)]
+phase_values = [str(i * 5) + "deg" for i in range(18)]
animated = aedtapp.post.plot_animated_field(
quantity="Mag_E",
object_list=cutlist,
plot_type="CutPlane",
setup_name=aedtapp.nominal_adaptive,
- intrinsics={"Freq": "1GHz", "Phase": "0deg"},
+ intrinsics=intrinsic,
export_path=results_folder,
variation_variable="Phase",
- variation_list=phases,
+ variation_list=phase_values,
show=False,
export_gif=False,
log_scale=True,
@@ -295,13 +300,14 @@
endtime = time.time() - start
print("Total Time", endtime)
+# -
-################################################################################
-# Create Icepak plots and export
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create Icepak plots and export
+#
# Create Icepak plots and export them as images using the same functions that
# were used early. Only the quantity is different.
+# +
quantity_name = "Temperature"
setup_name = ipkapp.existing_analysis_sweeps[0]
intrinsic = ""
@@ -309,10 +315,10 @@
plot5 = ipkapp.post.create_fieldplot_surface(surflist, "SurfTemperature")
aedtapp.save_project()
+# -
-################################################################################
-# Generate plots outside of AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Generate plots outside of AEDT
+#
# Generate plots outside of AEDT using Matplotlib and NumPy.
trace_names = aedtapp.get_traces_for_plot(category="S")
@@ -325,9 +331,8 @@
title="Scattering Chart",
snapshot_path=os.path.join(results_folder, "Touchstone_from_matplotlib.jpg"))
-################################################################################
-# Generate pdf report
-# ~~~~~~~~~~~~~~~~~~~
+# ## Generate pdf report
+#
# Generate a pdf report with output of simultion.
report = AnsysReport(project_name=aedtapp.project_name, design_name=aedtapp.design_name, version=desktopVersion)
report.create()
@@ -348,9 +353,11 @@
# report.add_image(os.path.join(results_folder, plot5.name+".jpg"), "Coaxial Cable Temperatures")
report.save_pdf(results_folder, "AEDT_Results.pdf")
-################################################################################
-# Close project and release AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Close project and release AEDT
+#
# Close the project and release AEDT.
aedtapp.release_desktop()
+
+temp_dir.cleanup() # Clean up temporary directory and delete project files.
diff --git a/examples/06-Multiphysics/Hfss_Mechanical.py b/examples/06-Multiphysics/Hfss_Mechanical.py
index ad4ecfa32ce..ac473c01505 100644
--- a/examples/06-Multiphysics/Hfss_Mechanical.py
+++ b/examples/06-Multiphysics/Hfss_Mechanical.py
@@ -1,36 +1,30 @@
-"""
-Multiphysics: HFSS-Mechanical multiphysics analysis
----------------------------------------------------
-This example shows how you can use PyAEDT to create a multiphysics workflow that
-includes Circuit, HFSS, and Mechanical.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Multiphysics: HFSS-Mechanical multiphysics analysis
+#
+# This example shows how you can use PyAEDT to create a multiphysics workflow that
+# includes Circuit, HFSS, and Mechanical.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
import pyaedt
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Download and open project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Download and open project
+#
# Download and open the project. Save it to the temporary folder.
project_temp_name = pyaedt.downloads.download_via_wizard(pyaedt.generate_unique_folder_name())
-###############################################################################
-# Start HFSS
-# ~~~~~~~~~~
+# ## Start HFSS
+#
# Start HFSS and initialize the PyAEDT object.
version = "2023.2"
@@ -39,17 +33,15 @@
pin_names = hfss.excitations
hfss.change_material_override(True)
-###############################################################################
-# Start Circuit
-# ~~~~~~~~~~~~~
+# ## Start Circuit
+#
# Start Circuit and add the HFSS dynamic link component to it.
circuit = pyaedt.Circuit()
hfss_comp = circuit.modeler.schematic.add_subcircuit_dynamic_link(hfss)
-###############################################################################
-# Set up dynamic link options
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set up dynamic link options
+#
# Set up dynamic link options. The argument for the ``set_sim_option_on_hfss_subcircuit``
# method can be the component name, component ID, or component object.
@@ -58,12 +50,12 @@
hfss_setup_name = hfss.setups[0].name + " : " + hfss.setups[0].sweeps[0].name
circuit.modeler.schematic.set_sim_solution_on_hfss_subcircuit(hfss_comp.composed_name, hfss_setup_name)
-###############################################################################
-# Create ports and excitations
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create ports and excitations
+#
# Create ports and excitations. Find component pin locations and create interface
# ports on them. Define the voltage source on the input port.
+# +
circuit.modeler.schematic.create_interface_port(
name="Excitation_1", location=[hfss_comp.pins[0].location[0], hfss_comp.pins[0].location[1]]
)
@@ -83,10 +75,10 @@
source = circuit.assign_voltage_sinusoidal_excitation_to_ports(ports_list)
source.ac_magnitude = voltage
source.phase = phase
+# -
-###############################################################################
-# Create setup
-# ~~~~~~~~~~~~
+# ## Create setup
+#
# Create a setup.
setup_name = "MySetup"
@@ -98,9 +90,8 @@
sweep_list = ["LINC", str(bw_start) + unit, str(bw_stop) + unit, str(n_points)]
LNA_setup.props["SweepDefinition"]["Data"] = " ".join(sweep_list)
-###############################################################################
-# Solve and push excitations
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Solve and push excitations
+#
# Solve the circuit and push excitations to the HFSS model to calculate the
# correct value of losses.
@@ -108,18 +99,16 @@
circuit.push_excitations(instance_name="S1", setup_name=setup_name)
-###############################################################################
-# Start Mechanical
-# ~~~~~~~~~~~~~~~~
+# ## Start Mechanical
+#
# Start Mechanical and copy bodies from the HFSS project.
mech = pyaedt.Mechanical()
mech.copy_solid_bodies_from(hfss)
mech.change_material_override(True)
-###############################################################################
-# Get losses from HFSS and assign convection to Mechanical
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get losses from HFSS and assign convection to Mechanical
+#
# Get losses from HFSS and assign the convection to Mechanical.
mech.assign_em_losses(
@@ -134,16 +123,14 @@
mech.assign_uniform_convection(objects_list=[mech.modeler[el].top_face_y, mech.modeler[el].bottom_face_y],
convection_value=3)
-###############################################################################
-# Plot model
-# ~~~~~~~~~~
+# ## Plot model
+#
# Plot the model.
mech.plot(show=False, export_path=os.path.join(mech.working_directory, "Mech.jpg"), plot_air_objects=False)
-###############################################################################
-# Solve and plot thermal results
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Solve and plot thermal results
+#
# Solve and plot the thermal results.
mech.create_setup()
@@ -154,9 +141,8 @@
surfaces.extend(mech.modeler.get_object_faces(name))
mech.post.create_fieldplot_surface(objlist=surfaces, quantityName="Temperature")
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
mech.release_desktop(True, True)
diff --git a/examples/06-Multiphysics/MRI.py b/examples/06-Multiphysics/MRI.py
index 47b94a38bcf..3f7243bf330 100644
--- a/examples/06-Multiphysics/MRI.py
+++ b/examples/06-Multiphysics/MRI.py
@@ -1,49 +1,44 @@
-"""
-Multiphysics: HFSS-Mechanical MRI analysis
----------------------------------------------------
-The goal of this workshop is to use a coil tuned to 63.8 MHz to determine the temperature
-rise in a gel phantom near an implant given a background SAR of 1 W/kg.
-
-Steps to follow
-Step 1: Simulate coil loaded by empty phantom:
-Scale input to coil ports to produce desired background SAR of 1 W/kg at location that will later contain the implant.
-Step 2: Simulate coil loaded by phantom containing implant in proper location:
-View SAR in tissue surrounding implant.
-Step 3: Thermal simulation:
-Link HFSS to transient thermal solver to find temperature rise in tissue near implant vs. time.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Multiphysics: HFSS-Mechanical MRI analysis
+#
+# The goal of this workshop is to use a coil tuned to 63.8 MHz to determine the temperature
+# rise in a gel phantom near an implant given a background SAR of 1 W/kg.
+#
+# Steps to follow
+# Step 1: Simulate coil loaded by empty phantom:
+# Scale input to coil ports to produce desired background SAR of 1 W/kg at location that will later contain the implant.
+# Step 2: Simulate coil loaded by phantom containing implant in proper location:
+# View SAR in tissue surrounding implant.
+# Step 3: Thermal simulation:
+# Link HFSS to transient thermal solver to find temperature rise in tissue near implant vs. time.
+
+# ## Perform required imports
# Perform required imports.
-import os.path
+import os.path
from pyaedt import Hfss, Mechanical, Icepak, downloads
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. `
# You can set ``non_graphical`` either to ``True`` or ``False``.
non_graphical = False
-###############################################################################
-# Project load
-# ~~~~~~~~~~~~
+# ## Project load
+#
# Open the ANSYS Electronics Desktop 2018.2
# Open project background_SAR.aedt
# Project contains phantom and airbox
# Phantom consists of two objects: phantom and implant_box
# Separate objects are used to selectively assign mesh operations
# Material properties defined in this project already contain #electrical and thermal properties.
+
project_path = downloads.download_file(directory="mri")
hfss = Hfss(os.path.join(project_path, "background_SAR.aedt"), specified_version="2023.2", non_graphical=non_graphical,
new_desktop_session=True)
-###############################################################################
-# Insert 3D component
-# ~~~~~~~~~~~~~~~~~~~
+
+# ## Insert 3D component
+#
# The MRI Coil is saved as a separate 3D Component
# ‒ 3D Components store geometry (including parameters),
# material properties, boundary conditions, mesh assignments,
@@ -52,14 +47,14 @@
hfss.modeler.insert_3d_component(os.path.join(project_path, "coil.a3dcomp"))
-###############################################################################
-# Expression Cache
-# ~~~~~~~~~~~~~~~~~
+# ## Expression Cache
+#
# On the expression cache tab, define additional convergence criteria for self impedance of the four coil
# ports
# ‒ Set each of these convergence criteria to 2.5 ohm
# For this demo number of passes is limited to 2 to reduce simulation time.
+# +
im_traces = hfss.get_traces_for_plot(get_mutual_terms=False, category="im(Z", first_element_filter="Coil1_p*")
hfss.setups[0].enable_expression_cache(
@@ -71,6 +66,7 @@
use_cache_for_freq=False)
hfss.setups[0].props["MaximumPasses"] = 2
im_traces
+# -
###############################################################################
# Edit Sources
diff --git a/examples/06-Multiphysics/Readme.txt b/examples/06-Multiphysics/index.rst
similarity index 74%
rename from examples/06-Multiphysics/Readme.txt
rename to examples/06-Multiphysics/index.rst
index d35019b7dbd..3feeb59f7f0 100644
--- a/examples/06-Multiphysics/Readme.txt
+++ b/examples/06-Multiphysics/index.rst
@@ -3,3 +3,9 @@ Multiphysics examples
These examples use PyAEDT to create some multiphysics workflows. They might use
an electromagnetic tool like HFSS or Maxwell and a thermal or structural tool
like Icepak or Mechanical.
+
+.. nbgallery::
+
+ Hfss_Icepak_Coupling.py
+ Hfss_Mechanical.py
+ MRI.py
\ No newline at end of file
diff --git a/examples/07-Circuit/Circuit_AMI.py b/examples/07-Circuit/Circuit_AMI.py
index 21045388daa..f21c20851d6 100644
--- a/examples/07-Circuit/Circuit_AMI.py
+++ b/examples/07-Circuit/Circuit_AMI.py
@@ -1,36 +1,42 @@
-"""
-Circuit: AMI PostProcessing
-----------------------------------
-This example shows how you can use PyAEDT to perform advanced postprocessing of AMI simulations.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports and set the local path to the path for PyAEDT.
+# # Circuit: AMI PostProcessing
+#
+# This example shows how you can use PyAEDT to perform advanced postprocessing of AMI simulations.
+
+#
-# sphinx_gallery_thumbnail_path = 'Resources/spectrum_plot.png'
+# ## Perform required imports
+#
+# Perform required imports and set the local path to the path for PyAEDT.
import os
from matplotlib import pyplot as plt
import numpy as np
-
import pyaedt
-
-# Set local path to path for PyAEDT
-temp_folder = pyaedt.generate_unique_folder_name()
-project_path = pyaedt.downloads.download_file("ami", "ami_usb.aedtz", temp_folder)
-
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+import tempfile
+
+# ## Download Example Data
+#
+# The ``download_file()`` method retrieves example
+# data from the PyAnsys _example-data_ repository.
+#
+# - The fist argument is the folder name where
+# the example files are located in the GitHub repository.
+# - The 2nd argument is the file to retrieve.
+# - The 3rd argument is the desination folder.
+#
+# Files are placed in the destination folder.
+
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+project_path = pyaedt.downloads.download_file("ami", "ami_usb.aedtz", temp_dir.name)
+
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode. This example uses SI units.
desktopVersion = "2023.2"
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The Boolean parameter ``new_thread`` defines whether to create a new instance
@@ -39,27 +45,24 @@
non_graphical = False
NewThread = True
-###############################################################################
-# Launch AEDT with Circuit and enable Pandas as the output format
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with Circuit and enable Pandas as the output format
+#
# All outputs obtained with the `get_solution_data` method will have the Pandas format.
-# Launch AEDT with Circuit. The :class:`pyaedt.Desktop` class initializes AEDT
+# Launch AEDT with Circuit. The `pyaedt.Desktop` class initializes AEDT
# and starts the specified version in the specified mode.
pyaedt.settings.enable_pandas_output = True
cir = pyaedt.Circuit(projectname=os.path.join(project_path), non_graphical=non_graphical,
specified_version=desktopVersion, new_desktop_session=NewThread)
-###############################################################################
-# Solve AMI setup
-# ~~~~~~~~~~~~~~~
+# ## Solve AMI setup
+#
# Solve the transient setup.
cir.analyze()
-###############################################################################
-# Get AMI report
-# ~~~~~~~~~~~~~~
+# ## Get AMI report
+#
# Get AMI report data
plot_name = "WaveAfterProbe"
@@ -71,17 +74,18 @@
original_data_sweep = original_data.primary_sweep_values
print(original_data_value)
-###############################################################################
-# Plot data
-# ~~~~~~~~~
+# ## Plot data
+#
# Create a plot based on solution data.
fig = original_data.plot()
-###############################################################################
-# Sample WaveAfterProbe waveform using receiver clock
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Extract waveform at specific clock time plus half unit interval
+# ## Extract Wave Form
+#
+# Use the _WaveAfterProbe_ plot type to extract the
+# waveform using an AMI receiver clock probe.
+# The signal is extracted at a specific clock
+# flank with addiional half unit interval.
probe_name = "b_input_43"
source_name = "b_output4_42"
@@ -89,16 +93,17 @@
setup_name = "AMIAnalysis"
ignore_bits = 100
unit_interval = 0.1e-9
-sample_waveform = cir.post.sample_ami_waveform(setupname=setup_name, probe_name=probe_name, source_name=source_name,
+sample_waveform = cir.post.sample_ami_waveform(setupname=setup_name, probe_name=probe_name,
+ source_name=source_name,
variation_list_w_value=cir.available_variations.nominal,
unit_interval=unit_interval, ignore_bits=ignore_bits,
plot_type=plot_type)
-###############################################################################
-# Plot waveform and samples
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot waveform and samples
+#
# Create the plot from a start time to stop time in seconds
+# +
tstop = 55e-9
tstart = 50e-9
scale_time = pyaedt.constants.unit_converter(1, unit_system="Time", input_units="s",
@@ -139,10 +144,10 @@
ax.set_xlabel(original_data.units_sweeps["Time"])
ax.set_ylabel(original_data.units_data[plot_name])
plt.show()
+# -
-###############################################################################
-# Plot Slicer Scatter
-# ~~~~~~~~~~~~~~~~~~~
+# ## Plot Slicer Scatter
+#
# Create the plot from a start time to stop time in seconds
fig, ax2 = plt.subplots()
@@ -152,9 +157,8 @@
ax2.set_ylabel("V")
plt.show()
-###############################################################################
-# Plot scatter histogram
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot scatter histogram
+#
# Create the plot from a start time to stop time in seconds.
fig, ax4 = plt.subplots()
@@ -164,9 +168,8 @@
ax4.grid()
plt.show()
-###############################################################################
-# Get Transient report
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Get Transient report
+#
# Get Transient report data
plot_name = "V(b_input_43.int_ami_rx.eye_probe.out)"
@@ -175,11 +178,11 @@
setup_sweep_name="NexximTransient", domain="Time",
variations=cir.available_variations.nominal)
-###############################################################################
-# Sample waveform using a user-defined clock
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Sample waveform using a user-defined clock
+#
# Extract waveform at specific clock time plus half unit interval.
+# +
original_data.enable_pandas_output = False
original_data_value = original_data.data_real()
original_data_sweep = original_data.primary_sweep_values
@@ -196,12 +199,13 @@
clock_tics=tics,
pandas_enabled=False,
)
+# -
-###############################################################################
-# Plot waveform and samples
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Plot waveform and samples
+#
# Create the plot from a start time to stop time in seconds.
+# +
tstop = 40.0e-9
tstart = 25.0e-9
scale_time = pyaedt.constants.unit_converter(1, unit_system="Time", input_units="s",
@@ -247,10 +251,10 @@
ax.set_xlabel(waveform_sweep_unit)
ax.set_ylabel(waveform_unit)
plt.show()
+# -
-###############################################################################
-# Plot slicer scatter
-# ~~~~~~~~~~~~~~~~~~~
+# ## Plot slicer scatter
+#
# Create the plot from a start time to stop time in seconds.
sample_waveform_array = np.array(sample_waveform)
@@ -261,11 +265,12 @@
ax2.set_ylabel("V")
plt.show()
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
cir.save_project()
print("Project Saved in {}".format(cir.project_path))
cir.release_desktop()
+
+temp_dir.cleanup() # Remove project folder and temporary files.
diff --git a/examples/07-Circuit/Circuit_Example.py b/examples/07-Circuit/Circuit_Example.py
index 673c091f8b0..d817ad21fba 100644
--- a/examples/07-Circuit/Circuit_Example.py
+++ b/examples/07-Circuit/Circuit_Example.py
@@ -1,108 +1,107 @@
-"""
-Circuit: schematic creation and analysis
-----------------------------------------
-This example shows how you can use PyAEDT to create a circuit design
-and run a Nexxim time-domain simulation.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Circuit: schematic creation and analysis
+#
+# This example shows how to build a circuit schematic
+# and run a transient circuit simulation.
+
+#
+#
+# ## Perform required imports
+#
# Perform required imports.
-# sphinx_gallery_thumbnail_path = 'Resources/circuit.png'
-
import pyaedt
+import tempfile
+import os
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode. This example uses SI units.
-desktop_version = "2023.2"
-
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The Boolean parameter ``new_thread`` defines whether to create a new instance
# of AEDT or try to connect to an existing instance of it.
-non_graphical = False
-new_thread = True
-
-###############################################################################
-# Launch AEDT and Circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT and Circuit
+#
# Launch AEDT and Circuit. The :class:`pyaedt.Desktop` class initializes AEDT and
# starts the specified version in the specified mode.
+# +
+desktop_version = "2023.2"
+non_graphical = False
+new_thread = True
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+
desktop = pyaedt.launch_desktop(desktop_version, non_graphical, new_thread)
-aedt_app = pyaedt.Circuit(projectname=pyaedt.generate_unique_project_name())
+aedt_app = pyaedt.Circuit(projectname=os.path.join(temp_dir.name, "CircuitExample"),
+ designname="Simple")
aedt_app.modeler.schematic.schematic_units = "mil"
-###############################################################################
-# Create circuit setup
-# ~~~~~~~~~~~~~~~~~~~~
-# Create and customize an LNA (linear network analysis) setup.
+# -
+
+# ## Create circuit setup
+#
+# Create and customize an linear network analysis (LNA) setup.
setup1 = aedt_app.create_setup("MyLNA")
setup1.props["SweepDefinition"]["Data"] = "LINC 0GHz 4GHz 10001"
-###############################################################################
-# Create components
-# ~~~~~~~~~~~~~~~~~
-# Create components, such as an inductor, resistor, and capacitor.
+# ## Place Components
+#
+# Place components such as an inductor, resistor, and capacitor. The ``location`` argument
+# provides the ``[x, y]`` coordinates to place the component.
inductor = aedt_app.modeler.schematic.create_inductor(compname="L1", value=1e-9, location=[0, 0])
resistor = aedt_app.modeler.schematic.create_resistor(compname="R1", value=50, location=[500, 0])
capacitor = aedt_app.modeler.schematic.create_capacitor(compname="C1", value=1e-12, location=[1000, 0])
-###############################################################################
-# Get all pins
-# ~~~~~~~~~~~~
-# Get all pins of a specified component.
-
-pins_resistor = resistor.pins
-
-###############################################################################
-# Create port and ground
-# ~~~~~~~~~~~~~~~~~~~~~~
-# Create a port and a ground, which are needed for the circuit analysis.
-
-port = aedt_app.modeler.components.create_interface_port(name="myport", location=[-200, 0] )
+# ## Get all pins
+#
+# The component pins are instances of the class
+# ``pyaedt.modeler.circuits.objct3dcircuit.CircuitPins`` class and
+# provide access to the
+# pin location, net connectivity and the method ``connect_to_component()`` which
+# can be used to connect components in the schematic
+# as will be demonstrated in
+# this example.
+
+# ## Place a Port and Ground
+#
+# Place a port and a ground in the schematic.
+
+port = aedt_app.modeler.components.create_interface_port(name="myport", location=[-300, 50] )
gnd = aedt_app.modeler.components.create_gnd(location=[1200, -100])
-###############################################################################
-# Connect components
-# ~~~~~~~~~~~~~~~~~~
-# Connect components with wires.
+# ## Connect components
+#
+# Connect components with wires in the schematic. The ``connect_to_component()``
+# method is used to create connections between pins.
port.pins[0].connect_to_component(component_pin=inductor.pins[0], use_wire=True)
inductor.pins[1].connect_to_component(component_pin=resistor.pins[1], use_wire=True)
resistor.pins[0].connect_to_component(component_pin=capacitor.pins[0], use_wire=True)
capacitor.pins[1].connect_to_component(component_pin=gnd.pins[0], use_wire=True)
-###############################################################################
-# Create transient setup
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create transient setup
+#
# Create a transient setup.
setup2 = aedt_app.create_setup(setupname="MyTransient", setuptype=aedt_app.SETUPS.NexximTransient)
setup2.props["TransientData"] = ["0.01ns", "200ns"]
setup3 = aedt_app.create_setup(setupname="MyDC", setuptype=aedt_app.SETUPS.NexximDC)
-###############################################################################
-# Solve transient setup
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Solve transient setup
+#
# Solve the transient setup.
aedt_app.analyze_setup("MyLNA")
aedt_app.export_fullwave_spice()
-###############################################################################
-# Create report
-# ~~~~~~~~~~~~~
-# Create a report that plots solution data.
+# ## Create report
+#
+# Display the scattering parameters.
solutions = aedt_app.post.get_solution_data(
expressions=aedt_app.get_traces_for_plot(category="S"),
@@ -111,18 +110,18 @@
real, imag = solutions.full_matrix_real_imag
print(real)
-###############################################################################
-# Plot data
-# ~~~~~~~~~
+# ## Plot data
+#
# Create a plot based on solution data.
fig = solutions.plot()
-###############################################################################
-# Close AEDT
-# ~~~~~~~~~~
+# ## Close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.force_close_desktop` method.
# All methods provide for saving the project before closing.
desktop.release_desktop()
+
+temp_dir.cleanup() # Remove project data and temporary working directory.
diff --git a/examples/07-Circuit/Circuit_Siwave_Multizones.py b/examples/07-Circuit/Circuit_Siwave_Multizones.py
index 25dc68945bf..fb9968a2c14 100644
--- a/examples/07-Circuit/Circuit_Siwave_Multizones.py
+++ b/examples/07-Circuit/Circuit_Siwave_Multizones.py
@@ -1,110 +1,101 @@
-"""
-Circuit: Simulate multi-zones layout with Siwave
-------------------------------------------------
-This example shows how you can use PyAEDT simulate multi-zones with Siwave.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Circuit: Simulate multi-zones layout with Siwave
+#
+# This example shows how you can use PyAEDT simulate multi-zones with Siwave.
+
+# ## Perform required imports
+#
# Perform required imports, which includes importing a section.
from pyaedt import Edb, Circuit
import os.path
import pyaedt
+import tempfile
-###############################################################################
-# Download file
-# ~~~~~~~~~~~~~
+# ## Download file
+#
# Download the AEDB file and copy it in the temporary folder.
-temp_folder = pyaedt.generate_unique_folder_name()
-edb_file = pyaedt.downloads.download_file(destination=temp_folder, directory="edb/siwave_multi_zones.aedb")
-working_directory = os.path.join(temp_folder, "workdir")
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+edb_file = pyaedt.downloads.download_file(destination=temp_dir.name, directory="edb/siwave_multi_zones.aedb")
aedt_file = os.path.splitext(edb_file)[0] + ".aedt"
-circuit_project_file = os.path.join(working_directory, os.path.splitext(os.path.basename(edb_file))[0] +
- "multizone_clipped_circuit.aedt")
+circuit_project_file = os.path.join(temp_dir.name, "multizone_clipped_circuit.aedt")
print(edb_file)
-###############################################################################
-# AEDT version
-# ~~~~~~~~~~~~
+# ## AEDT version
+#
# Sets the Aedt version to 2023 R2.
edb_version = "2023.2"
-#####################################################################################
-# Ground net
-# ~~~~~~~~~~
+# ## Ground net
+#
# Common reference net used across all sub-designs, Mandatory for this work flow.
common_reference_net = "GND"
-########################################################################################
-# Project load
-# ~~~~~~~~~~~~
+# ## Project load
+#
# Load initial Edb file, checking if aedt file exists and remove to allow Edb loading.
if os.path.isfile(aedt_file):
os.remove(aedt_file)
edb = Edb(edbversion=edb_version, edbpath=edb_file)
-###############################################################################
-# Project zones
-# ~~~~~~~~~~~~~
+# ## Project zones
+#
# Copy project zone into sub project.
edb_zones = edb.copy_zones(working_directory=working_directory)
-###############################################################################
-# Split zones
-# ~~~~~~~~~~~
+# ## Split zones
+#
# Clip sub-designs along with corresponding zone definition
# and create port of clipped signal traces.
+
defined_ports, project_connexions = edb.cutout_multizone_layout(edb_zones, common_reference_net)
-#############################################################################################################
-# Circuit
-# ~~~~~~~
+# ## Circuit
+#
# Create circuit design, import all sub-project as EM model and connect all corresponding pins in circuit.
circuit = Circuit(specified_version=edb_version, projectname=circuit_project_file)
circuit.connect_circuit_models_from_multi_zone_cutout(project_connections=project_connexions,
edb_zones_dict=edb_zones, ports=defined_ports,
model_inc=70)
-###############################################################################
-# Setup
-# ~~~~~
-# Add Nexxim LNA simulation setup.
+
+# ## Setup
+#
+# Add Nexxim LNA simulation setup.
+
circuit_setup= circuit.create_setup("Pyedt_LNA")
-###############################################################################
-# Frequency sweep
-# ~~~~~~~~~~~~~~~
+# ## Frequency sweep
+#
# Add frequency sweep from 0GHt to 20GHz with 10NHz frequency step.
+
circuit_setup.props["SweepDefinition"]["Data"] = "LIN {} {} {}".format("0GHz", "20GHz", "10MHz")
-###############################################################################
-# Start simulation
-# ~~~~~~~~~~~~~~~~
+# ## Start simulation
+#
# Analyze all siwave projects and solves the circuit.
+
circuit.analyze()
-###############################################################################
# Define differential pairs
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+
circuit.set_differential_pair(diff_name="U0", positive_terminal="U0.via_38.B2B_SIGP",
negative_terminal="U0.via_39.B2B_SIGN")
circuit.set_differential_pair(diff_name="U1", positive_terminal="U1.via_32.B2B_SIGP",
negative_terminal="U1.via_33.B2B_SIGN")
-###############################################################################
# Plot results
-# ~~~~~~~~~~~~
+
circuit.post.create_report(expressions=["dB(S(U0,U0))", "dB(S(U1,U0))"], context="Differential Pairs")
-###############################################################################
-# Release AEDT desktop
-# ~~~~~~~~~~~~~~~~~~~~
-circuit.release_desktop()
\ No newline at end of file
+# ## Release AEDT desktop
+#
+
+circuit.release_desktop()
+
+temp_dir.cleanup() # Remove the temporary working folder and all project files
diff --git a/examples/07-Circuit/Circuit_Subcircuit_Example.py b/examples/07-Circuit/Circuit_Subcircuit_Example.py
index ed2cffd087e..61ae277b748 100644
--- a/examples/07-Circuit/Circuit_Subcircuit_Example.py
+++ b/examples/07-Circuit/Circuit_Subcircuit_Example.py
@@ -1,41 +1,38 @@
-"""
-Circuit: schematic subcircuit management
-----------------------------------------
-This example shows how you can use PyAEDT to add a subcircuit to a circuit design.
-It pushes down the child subcircuit and pops up to the parent design.
-"""
-##########################################################
-# Perform required import
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# # Circuit: schematic subcircuit management
+#
+# This example shows how you can use PyAEDT to add a subcircuit to a circuit design.
+# It pushes down the child subcircuit and pops up to the parent design.
+
+# ## Perform required import
+#
# Perform the required import.
import os
import pyaedt
+import tempfile
-##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
-non_graphical = False
-
-###############################################################################
-# Launch AEDT with Circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with Circuit
+#
# Launch AEDT 2023 R2 in graphical mode with Circuit.
-circuit = pyaedt.Circuit(projectname=pyaedt.generate_unique_project_name(),
- specified_version="2023.2",
- non_graphical=non_graphical,
- new_desktop_session=True
- )
+non_graphical = False
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+circuit = pyaedt.Circuit(projectname=os.path.join(temp_dir.name, "SubcircuitExample"),
+ designname="SimpleExample",
+ specified_version="2023.2",
+ non_graphical=non_graphical,
+ new_desktop_session=True
+ )
circuit.modeler.schematic_units = "mil"
-###############################################################################
-# Add subcircuit
-# ~~~~~~~~~~~~~~
+# ## Add subcircuit
+#
# Add a new subcircuit to the previously created circuit design, creating a
# child circuit. Push this child circuit down into the child subcircuit.
@@ -43,9 +40,8 @@
subcircuit_name = subcircuit.composed_name
circuit.push_down(subcircuit)
-###############################################################################
-# Parametrize subcircuit
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Parametrize subcircuit
+#
# Parametrize the subcircuit and add a resistor, inductor, and a capacitor with
# the parameter values in the following code example. Connect them in series
# and then use the ``pop_up`` # method to get back to the parent design.
@@ -62,9 +58,10 @@
circuit.pop_up()
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
circuit.release_desktop(True, True)
+
+temp_dir.cleanup() # Clean up temporary folder and remove project data.
diff --git a/examples/07-Circuit/Circuit_Transient.py b/examples/07-Circuit/Circuit_Transient.py
index 4f1f1fa994c..b2d8bc0c3fd 100644
--- a/examples/07-Circuit/Circuit_Transient.py
+++ b/examples/07-Circuit/Circuit_Transient.py
@@ -1,75 +1,69 @@
-"""
-Circuit: transient analysis and eye plot
-----------------------------------------
-This example shows how you can use PyAEDT to create a circuit design,
-run a Nexxim time-domain simulation, and create an eye diagram.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Circuit: transient analysis and eye plot
+#
+# This example shows how you can use PyAEDT to create a circuit design,
+# run a Nexxim time-domain simulation, and create an eye diagram.
+
+
+# ## Perform required imports
+#
# Perform required imports.
import os
from matplotlib import pyplot as plt
import numpy as np
import pyaedt
+import tempfile
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode, ``"PYAEDT_NON_GRAPHICAL"`` is needed to generate
# documentation only.
# You can set ``non_graphical`` either to ``True`` or ``False``.
-non_graphical = False
-
-###############################################################################
-# Launch AEDT with Circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with Circuit
+#
# Launch AEDT 2023 R2 in graphical mode with Circuit.
-cir = pyaedt.Circuit(projectname=pyaedt.generate_unique_project_name(),
+non_graphical = False
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+cir = pyaedt.Circuit(projectname=os.path.join(temp_dir.name, "CktTransient"),
+ designname="Circuit Examples",
specified_version="2023.2",
new_desktop_session=True,
non_graphical=non_graphical
)
-###############################################################################
-# Read IBIS file
-# ~~~~~~~~~~~~~~
+# ## Read IBIS file
+#
# Read an IBIS file and place a buffer in the schematic.
ibis = cir.get_ibis_model_from_file(os.path.join(cir.desktop_install_dir, 'buflib', 'IBIS', 'u26a_800.ibs'))
ibs = ibis.buffers["DQ_u26a_800"].insert(0, 0)
-###############################################################################
-# Place ideal transmission line
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Place ideal transmission line
+#
# Place an ideal transmission line in the schematic and parametrize it.
tr1 = cir.modeler.components.components_catalog["Ideal Distributed:TRLK_NX"].place("tr1")
tr1.parameters["P"] = "50mm"
-###############################################################################
-# Create resistor and ground
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create resistor and ground
+#
# Create a resistor and ground in the schematic.
res = cir.modeler.components.create_resistor(compname="R1", value="1Meg")
gnd1 = cir.modeler.components.create_gnd()
-###############################################################################
-# Connect elements
-# ~~~~~~~~~~~~~~~~
+# ## Connect elements
+#
# Connect elements in the schematic.
tr1.pins[0].connect_to_component(ibs.pins[0])
tr1.pins[1].connect_to_component(res.pins[0])
res.pins[1].connect_to_component(gnd1.pins[0])
-###############################################################################
-# Place probe
-# ~~~~~~~~~~~
+# ## Place probe
+#
# Place a probe and rename it to ``Vout``.
pr1 = cir.modeler.components.components_catalog["Probes:VPROBE"].place("vout")
@@ -79,21 +73,19 @@
pr2.parameters["Name"] = "Vin"
pr2.pins[0].connect_to_component(ibs.pins[0])
-###############################################################################
-# Create setup and analyze
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create setup and analyze
+#
# Create a transient analysis setup and analyze it.
trans_setup = cir.create_setup(setupname="TransientRun", setuptype="NexximTransient")
trans_setup.props["TransientData"] = ["0.01ns", "200ns"]
cir.analyze_setup("TransientRun")
-###############################################################################
-# Create report outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create a report outside AEDT using the ``get_solution_data`` method. This
-# method allows you to get solution data and plot it outside AEDT without needing
-# a UI.
+# ## View Results
+#
+# Create a report using the ``get_solution_data()`` method. This
+# method allows you to view and post-process results using Python packages.
+# The ``solutions.plot()`` method uses Matplotlib.
report = cir.post.create_report("V(Vout)", domain="Time")
if not non_graphical:
@@ -101,9 +93,8 @@
solutions = cir.post.get_solution_data(domain="Time")
solutions.plot("V(Vout)")
-###############################################################################
-# Create report inside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create a Report in AEDT
+#
# Create a report inside AEDT using the ``new_report`` object. This object is
# fully customizable and usable with most of the reports available in AEDT.
# The standard report is the main one used in Circuit and Twin Builder.
@@ -126,9 +117,8 @@
sol = new_report.get_solution_data()
sol.plot()
-###############################################################################
-# Create eye diagram inside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create Eye Diagram in AEDT
+#
# Create an eye diagram inside AEDT using the ``new_eye`` object.
new_eye = cir.post.reports_by_category.eye_diagram("V(Vout)")
@@ -136,12 +126,12 @@
new_eye.time_stop = "100ns"
new_eye.create()
-###############################################################################
-# Create eye diagram outside AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create eye diagram outside AEDT
+#
# Create the same eye diagram outside AEDT using Matplotlib and the
-# ``get_solution_data`` method.
+# ``get_solution_data()`` method.
+# +
unit_interval = 1
offset = 0.25
tstop = 200
@@ -167,10 +157,13 @@
cellsv = np.append(cellsv, bn)
plt.plot(cellst.T, cellsv.T, zorder=0)
plt.show()
+# -
-###############################################################################
-# Release AEDT
-# ~~~~~~~~~~~~
+# ## Release AEDT
+#
# Release AEDT.
+
cir.save_project()
cir.release_desktop()
+
+temp_dir.cleanup() # Clean up temporary working folder and project files.
diff --git a/examples/07-Circuit/Create_Netlist.py b/examples/07-Circuit/Create_Netlist.py
index e71a1de0778..93e97f0df08 100644
--- a/examples/07-Circuit/Create_Netlist.py
+++ b/examples/07-Circuit/Create_Netlist.py
@@ -1,70 +1,61 @@
-"""
-Circuit: netlist to schematic import
-------------------------------------
-This example shows how you can import netlist data into a circuit design.
-HSPICE files are fully supported. Mentor files are partially supported.
-"""
+# # Circuit: netlist to schematic import
+#
+# This example shows how you can import netlist data into a circuit design.
+# HSPICE files are fully supported. Mentor files are partially supported.
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports and set paths.
import os
-
import pyaedt
+import tempfile
-netlist = pyaedt.downloads.download_netlist()
-
-project_name = pyaedt.generate_unique_project_name()
-print(project_name)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+netlist = pyaedt.downloads.download_netlist(destination=temp_dir.name)
-###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode. This example uses SI units.
-desktopVersion = "2023.2"
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The Boolean parameter ``NewThread`` defines whether to create a new instance
# of AEDT or try to connect to an existing instance of it.
+desktopVersion = "2023.2"
non_graphical = False
NewThread = True
-###############################################################################
-# Launch AEDT with Circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Launch AEDT with Circuit. The :class:`pyaedt.Desktop` class initializes AEDT
+# ## Launch AEDT with Circuit
+#
+# Launch AEDT with Circuit. The `pyaedt.Desktop` class initializes AEDT
# and starts it on the specified version in the specified graphical mode.
desktop = pyaedt.launch_desktop(desktopVersion, non_graphical, NewThread)
-aedtapp = pyaedt.Circuit(projectname=project_name)
+aedtapp = pyaedt.Circuit(projectname=os.path.join(temp_dir.name, "NetlistExample"))
-###############################################################################
-# Define variable
-# ~~~~~~~~~~~~~~~
-# Define a design variable by using a ``$`` prefix.
+# ## Define a Parameter
+#
+# Specify the voltage as a parameter.
aedtapp["Voltage"] = "5"
-###############################################################################
-# Create schematic from netlist file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create schematic from netlist file
+#
# Create a schematic from a netlist file. The ``create_schematic_from_netlist``
# method reads the netlist file and parses it. All components are parsed
# but only these categories are mapped: R, L, C, Q, U, J, V, and I.
aedtapp.create_schematic_from_netlist(netlist)
-###############################################################################
-# Close project and release AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Close project and release AEDT
+#
# After adding any other desired functionalities, close the project and release
# AEDT.
desktop.release_desktop()
+
+temp_dir.cleanup() # Clean up temporary directory and project data.
diff --git a/examples/07-Circuit/Readme.txt b/examples/07-Circuit/Readme.txt
deleted file mode 100644
index 85222d203e1..00000000000
--- a/examples/07-Circuit/Readme.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-Circuit examples
-~~~~~~~~~~~~~~~~
-These examples use PyAEDT to show some end-to-end workflows for Circuit.
-This includes schematic generation, setup, and postprocessing.
-
diff --git a/examples/07-Circuit/Reports.py b/examples/07-Circuit/Reports.py
index d4995032595..39349a9b17c 100644
--- a/examples/07-Circuit/Reports.py
+++ b/examples/07-Circuit/Reports.py
@@ -5,28 +5,30 @@
"""
###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports and set the local path to the path for PyAEDT.
import os
from IPython.display import Image
import pyaedt
+import tempfile
+""
# Set local path to path for PyAEDT
-temp_folder = pyaedt.generate_unique_folder_name()
-project_path = pyaedt.downloads.download_custom_reports(destination=temp_folder)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+project_path = pyaedt.downloads.download_custom_reports(destination=temp_dir.name)
###############################################################################
-# Launch AEDT
-# ~~~~~~~~~~~
+# ## Launch AEDT
+#
# Launch AEDT 2023 R2 in graphical mode. This example uses SI units.
desktopVersion = "2023.2"
##########################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The Boolean parameter ``new_thread`` defines whether to create a new instance
@@ -36,12 +38,12 @@
NewThread = True
###############################################################################
-# Launch AEDT with Circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with Circuit
+#
# Launch AEDT with Circuit. The :class:`pyaedt.Desktop` class initializes AEDT
# and starts the specified version in the specified mode.
-cir = pyaedt.Circuit(projectname=os.path.join(project_path, 'CISPR25_Radiated_Emissions_Example23R1.aedtz'),
+cir = pyaedt.Circuit(projectname=os.path.join(temp_dir.name, 'CISPR25_Radiated_Emissions_Example23R1.aedtz'),
non_graphical=non_graphical,
specified_version=desktopVersion,
new_desktop_session=True
@@ -49,8 +51,8 @@
cir.analyze()
###############################################################################
-# Create spectrum report
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create spectrum report
+#
# Create a spectrum report. You can use a JSON file to create a simple setup
# or a fully customized one. The following code creates a simple setup and changes
# the JSON file to customize it. In a spectrum report, you can add limitilines and
@@ -62,22 +64,21 @@
Image(out)
###############################################################################
-# Create spectrum report
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Create spectrum report
+#
# Every aspect of the report can be customized.
report1_full = cir.post.create_report_from_configuration(os.path.join(project_path,'Spectrum_CISPR_Custom.json'))
out = cir.post.export_report_to_jpg(cir.working_directory, report1_full.plot_name)
Image(out)
###############################################################################
-# Create transient report
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create transient report
+#
# Create a transient report. You can read and modify the JSON file
# before running the script. The following code modifies the traces
# before generating the report. You can create custom reports in non-graphical
# mode in AEDT 2023 R2 and later.
-
props = pyaedt.general_methods.read_json(os.path.join(project_path, 'Transient_CISPR_Custom.json'))
report2 = cir.post.create_report_from_configuration(input_dict=props, solution_name="NexximTransient")
@@ -85,8 +86,8 @@
Image(out)
###############################################################################
-# Create transient report
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create transient report
+#
# Property dictionary can be customized in any aspect and new report can be created easily.
# In this example the curve name is customized.
@@ -97,8 +98,8 @@
Image(out)
###############################################################################
-# Create eye diagram
-# ~~~~~~~~~~~~~~~~~~
+# ## Create eye diagram
+#
# Create an eye diagram. If the JSON file contains an eye mask, you can create
# an eye diagram and fully customize it.
@@ -107,8 +108,8 @@
Image(out)
###############################################################################
-# Create eye diagram
-# ~~~~~~~~~~~~~~~~~~
+# ## Create eye diagram
+#
# You can create custom reports in
# non-graphical mode in AEDT 2023 R2 and later.
@@ -118,13 +119,17 @@
Image(out)
################################################
# This is how the spectrum looks like
-# .. image:: Resources/spectrum_plot.png
+#
+#
###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# Save the project and close AEDT.
cir.save_project()
print("Project Saved in {}".format(cir.project_path))
cir.release_desktop()
+
+""
+temp_dir.cleanup() # Clean up project folder and remove files.
diff --git a/examples/07-Circuit/Touchstone_Management.py b/examples/07-Circuit/Touchstone_Management.py
index 6a192e1249f..7458eab9c1d 100644
--- a/examples/07-Circuit/Touchstone_Management.py
+++ b/examples/07-Circuit/Touchstone_Management.py
@@ -9,46 +9,41 @@
This example runs only on Windows using CPython.
"""
###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Perform required imports
+#
# Perform required imports and set the local path to the path for PyAEDT.
from pyaedt import downloads
-
example_path = downloads.download_touchstone()
###############################################################################
-# Import libraries and Touchstone file
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Import libraries and Touchstone file
+#
# Import Matplotlib, NumPy, and the Touchstone file.
from pyaedt.generic.touchstone_parser import read_touchstone
###############################################################################
-# Read Touchstone file
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Read Touchstone file
+#
# Read the Touchstone file.
data = read_touchstone(example_path)
###############################################################################
-# Get curve plot
-# ~~~~~~~~~~~~~~
+# ## Get curve plot
+#
# Get the curve plot by category. The following code shows how to plot lists of the return losses,
# insertion losses, fext, and next based on a few inputs and port names.
data.plot_return_losses()
-
data.plot_insertion_losses()
-
data.plot_next_xtalk_losses("U1")
-
data.plot_fext_xtalk_losses(tx_prefix="U1", rx_prefix="U7")
-
###############################################################################
-# Get curve worst cases
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Get curve worst cases
+#
# Get curve worst cases.
worst_rl, global_mean = data.get_worst_curve(
diff --git a/doc/source/Resources/circuit.png b/examples/07-Circuit/_static/circuit.png
similarity index 100%
rename from doc/source/Resources/circuit.png
rename to examples/07-Circuit/_static/circuit.png
diff --git a/doc/source/Resources/spectrum_plot.png b/examples/07-Circuit/_static/spectrum_plot.png
similarity index 100%
rename from doc/source/Resources/spectrum_plot.png
rename to examples/07-Circuit/_static/spectrum_plot.png
diff --git a/examples/07-Circuit/index.rst b/examples/07-Circuit/index.rst
new file mode 100644
index 00000000000..5cedc20bae8
--- /dev/null
+++ b/examples/07-Circuit/index.rst
@@ -0,0 +1,15 @@
+Circuit examples
+~~~~~~~~~~~~~~~~
+These examples use PyAEDT to show some end-to-end workflows for Circuit.
+This includes schematic generation, setup, and postprocessing.
+
+.. nbgallery::
+
+ Circuit_AMI.py
+ Circuit_Example.py
+ Circuit_Siwave_Multizones.py
+ Circuit_Subcircuit_Example.py
+ Circuit_Transient.py
+ Create_Netlist.py
+ Reports.py
+ Touchstone_Management.py
\ No newline at end of file
diff --git a/examples/07-EMIT/ComputeInterferenceType.py b/examples/07-EMIT/ComputeInterferenceType.py
index dfe37528795..568af83ab44 100644
--- a/examples/07-EMIT/ComputeInterferenceType.py
+++ b/examples/07-EMIT/ComputeInterferenceType.py
@@ -1,14 +1,12 @@
-"""
-EMIT: Classify interference type
---------------------------------
-This example shows how you can use PyAEDT to load an existing AEDT
-project with an EMIT design and analyze the results to classify the
-worst-case interference.
-"""
-###############################################################################
+# # EMIT: Classify Interference Type
+#
+# This example shows how to load an existing AEDT EMIT
+# design and analyze the results to classify the
+# worst-case interference.
+
+# +
# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+
import sys
from pyaedt.emit_core.emit_constants import InterfererType, ResultType, TxRxMode
from pyaedt import Emit
@@ -16,8 +14,16 @@
import os
import pyaedt.generic.constants as consts
import subprocess
+# -
+
+# ## Python Dependencies
+#
+# The followig cell can be run to make sure the ``plotly`` package is installed
+# in the current Python environment. If ``plotly`` is installed there is no need
+# to run this cell.
-# Check to see which Python libraries have been installed
+# +
+# Check to see which Python packages have been installed
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]
@@ -25,7 +31,8 @@
def install(package):
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])
-# Install plotly library (if needed) to display legend and scenario matrix results (internet connection needed)
+# Install plotly (if needed) to display legend and
+# scenario matrix results (internet connection needed)
required_packages = ['plotly']
for package in required_packages:
if package not in installed_packages:
@@ -33,34 +40,33 @@ def install(package):
# Import plotly library
import plotly.graph_objects as go
+# -
-# Define colors for tables
-table_colors = {"green":'#7d73ca', "yellow":'#d359a2', "orange": '#ff6361', "red": '#ffa600', "white": '#ffffff'}
-header_color = 'grey'
+# Check that EMIT version 2023.2 or greater is installed.
-# Check for if emit version is compatible
desktop_version = "2023.2"
if desktop_version <= "2023.1":
print("Warning: this example requires AEDT 2023.2 or later.")
sys.exit()
-###############################################################################
-# Launch AEDT with EMIT
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with EMIT
+#
# Launch AEDT with EMIT. The ``Desktop`` class initializes AEDT and starts it
# on the specified version and in the specified graphical mode.
non_graphical = False
new_thread = True
-desktop = pyaedt.launch_desktop(desktop_version, non_graphical=non_graphical, new_desktop_session=new_thread)
+desktop = pyaedt.launch_desktop(desktop_version, non_graphical=non_graphical,
+ new_desktop_session=new_thread)
path_to_desktop_project = pyaedt.downloads.download_file("emit", "interference.aedtz")
emitapp = Emit(non_graphical=False, new_desktop_session=False, projectname=path_to_desktop_project)
-# Get all the radios in the project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get a List of Transmitters
+#
# Get lists of all transmitters and receivers in the project.
+
rev = emitapp.results.analyze()
tx_interferer = InterfererType().TRANSMITTERS
rx_radios = rev.get_receiver_names()
@@ -72,9 +78,8 @@ def install(package):
sys.exit()
-###############################################################################
-# Classify the interference
-# ~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Classify the interference
+#
# Iterate over all the transmitters and receivers and compute the power
# at the input to each receiver due to each of the transmitters. Computes
# which, if any, type of interference occurred.
@@ -83,9 +88,8 @@ def install(package):
all_colors=[]
all_colors, power_matrix = rev.interference_type_classification(domain, use_filter = False, filter_list = [])
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
# :func:`pyaedt.Desktop.force_close_desktop` method.
# All methods provide for saving the project before closing.
@@ -93,14 +97,19 @@ def install(package):
emitapp.save_project()
emitapp.release_desktop()
-###############################################################################
-# Create a scenario matrix view
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create a scenario matrix view
+#
# Create a scenario matrix view with the transmitters defined across the top
# and receivers down the left-most column. The power at the input to each
# receiver is shown in each cell of the matrix and color-coded based on the
# interference type.
+# Set up colors to visualize results in a table.
+
+table_colors = {"green":'#7d73ca', "yellow":'#d359a2', "orange": '#ff6361', "red": '#ffa600', "white": '#ffffff'}
+header_color = 'grey'
+
+
def create_scenario_view(emis, colors, tx_radios, rx_radios):
"""Create a scenario matrix-like table with the higher received
power for each Tx-Rx radio combination. The colors
@@ -145,9 +154,8 @@ def create_scenario_view(emis, colors, tx_radios, rx_radios):
)
fig.show()
-###############################################################################
-# Generate a legend
-# ~~~~~~~~~~~~~~~~~
+# ## Generate a legend
+#
# Define the interference types and colors used to display the results of
# the analysis.
@@ -183,9 +191,10 @@ def create_legend_table():
width = 600
)
fig.show()
+
if os.getenv("PYAEDT_DOC_GENERATION", "False") != "1":
# Create a scenario view for all the interference types
create_scenario_view(power_matrix, all_colors, tx_radios, rx_radios)
# Create a legend for the interference types
- create_legend_table()
\ No newline at end of file
+ create_legend_table()
diff --git a/examples/07-EMIT/ComputeProtectionLevels.py b/examples/07-EMIT/ComputeProtectionLevels.py
index 84a8ac45379..a0938ceb2cc 100644
--- a/examples/07-EMIT/ComputeProtectionLevels.py
+++ b/examples/07-EMIT/ComputeProtectionLevels.py
@@ -1,17 +1,12 @@
-"""
-EMIT: Compute receiver protection levels
-----------------------------------------
-This example shows how you can use PyAEDT to open an AEDT project with
-an EMIT design and analyze the results to determine if the received
-power at the input to each receiver exceeds the specified protection
-levels.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+# # EMIT: Compute receiver protection levels
+#
+# This example shows how to open an AEDT project with
+# an EMIT design and analyze the results to determine if the received
+# power at the input to each receiver exceeds the specified protection
+# levels.
#
-# sphinx_gallery_thumbnail_path = "Resources/emit_protection_levels.png"
+# Perform required imports
+
import os
import sys
import subprocess
@@ -19,7 +14,14 @@
from pyaedt import Emit
from pyaedt.emit_core.emit_constants import TxRxMode, ResultType, InterfererType
-# Check to see which Python libraries have been installed
+# ## Python Dependencies
+#
+# The followig cell can be run to make sure the ``plotly`` package is installed
+# in the current Python environment. If ``plotly`` is installed there is no need
+# to run this cell.
+
+# +
+# Check to see which Python packages have been installed
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]
@@ -35,10 +37,10 @@ def install(package):
# Import required modules
import plotly.graph_objects as go
+# -
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode. ``"PYAEDT_NON_GRAPHICAL"``` is needed to generate
# documentation only.
# You can set ``non_graphical`` either to ``True`` or ``False``.
@@ -49,22 +51,21 @@ def install(package):
new_thread = True
desktop_version = "2023.2"
-###############################################################################
-# Launch AEDT with EMIT
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with EMIT
+#
# Launch AEDT with EMIT. The ``Desktop`` class initializes AEDT and starts it
# on the specified version and in the specified graphical mode.
+#
+# Check that the correct version of EMIT is installed.
if desktop_version <= "2023.1":
print("Warning: this example requires AEDT 2023.2 or later.")
sys.exit()
-
d = pyaedt.launch_desktop(desktop_version, non_graphical, new_thread)
emitapp = Emit(pyaedt.generate_unique_project_name())
-###############################################################################
-# Specify the protection levels
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Specify the protection levels
+#
# The protection levels are specified in dBm.
# If the damage threshold is exceeded, permanent damage to the receiver front
# end may occur.
@@ -74,6 +75,7 @@ def install(package):
# Exceeding the desense threshold reduces the signal-to-noise ratio and can
# reduce the maximum range, maximum bandwidth, and/or the overall link quality.
+# +
header_color = 'grey'
damage_threshold = 30
overload_threshold = -4
@@ -81,40 +83,45 @@ def install(package):
desense_threshold = -104
protection_levels = [damage_threshold, overload_threshold, intermod_threshold, desense_threshold]
+# -
-###############################################################################
-# Create and connect EMIT components
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create and connect EMIT components
+#
# Set up the scenario with radios connected to antennas.
bluetooth, blue_ant = emitapp.modeler.components.create_radio_antenna("Bluetooth Low Energy (LE)", "Bluetooth")
gps, gps_ant = emitapp.modeler.components.create_radio_antenna("GPS Receiver", "GPS")
wifi, wifi_ant = emitapp.modeler.components.create_radio_antenna("WiFi - 802.11-2012", "WiFi")
-###############################################################################
-# Configure the radios
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Configure the radios
+#
# Enable the HR-DSSS bands for the Wi-Fi radio and set the power level
# for all transmit bands to -20 dBm.
+# +
bands = wifi.bands()
for band in bands:
if "HR-DSSS" in band.node_name:
if "Ch 1-13" in band.node_name:
band.enabled=True
band.set_band_power_level(-20)
-
+
# Reduce the bluetooth transmit power
bands = bluetooth.bands()
for band in bands:
band.set_band_power_level(-20)
+
+# -
+
def get_radio_node(radio_name):
"""Get the radio node that matches the
- given radio name.
- Arguments:
- radio_name: String name of the radio.
- Returns: Instance of the radio.
+ given radio name.
+
+ Arguments:
+ radio_name: String name of the radio.
+
+ Returns: Instance of the radio.
"""
if gps.name == radio_name:
radio = gps
@@ -132,16 +139,14 @@ def get_radio_node(radio_name):
else:
band.enabled=False
-###############################################################################
-# Load the results set
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Load the results set
+#
# Create a results revision and load it for analysis.
rev = emitapp.results.analyze()
-###############################################################################
-# Generate a legend
-# ~~~~~~~~~~~~~~~~~
+# ## Generate a legend
+#
# Define the thresholds and colors used to display the results of
# the protection level analysis.
@@ -177,9 +182,8 @@ def create_legend_table():
)
fig.show()
-###############################################################################
-# Create a scenario matrix view
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create a scenario matrix view
+#
# Create a scenario matrix view with the transmitters defined across the top
# and receivers down the left-most column. The power at the input to each
# receiver is shown in each cell of the matrix and color-coded based on the
@@ -221,22 +225,22 @@ def create_scenario_view(emis, colors, tx_radios, rx_radios):
)
fig.show()
-###############################################################################
-# Get all the radios in the project
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get all the radios in the project
+#
# Get lists of all transmitters and receivers in the project.
+
if os.getenv("PYAEDT_DOC_GENERATION", "False") != "1":
rev = emitapp.results.current_revision
rx_radios = rev.get_receiver_names()
tx_radios = rev.get_interferer_names(InterfererType.TRANSMITTERS)
domain = emitapp.results.interaction_domain()
-###############################################################################
-# Classify the results
-# ~~~~~~~~~~~~~~~~~~~~
+# ## Classify the results
+#
# Iterate over all the transmitters and receivers and compute the power
# at the input to each receiver due to each of the transmitters. Computes
# which, if any, protection levels are exceeded by these power levels.
+
if os.getenv("PYAEDT_DOC_GENERATION", "False") != "1":
power_matrix=[]
all_colors=[]
@@ -249,11 +253,10 @@ def create_scenario_view(emis, colors, tx_radios, rx_radios):
# Create a legend for the protection levels
create_legend_table()
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.force_close_desktop` method.
+# `pyaedt.Desktop.force_close_desktop` method.
# All methods provide for saving the project before closing.
emitapp.save_project()
diff --git a/examples/07-EMIT/EMIT_Example.py b/examples/07-EMIT/EMIT_Example.py
index 3de88c6148e..1b83b4199de 100644
--- a/examples/07-EMIT/EMIT_Example.py
+++ b/examples/07-EMIT/EMIT_Example.py
@@ -1,24 +1,22 @@
-"""
-EMIT: antenna
----------------------
-This example shows how you can use PyAEDT to create a project in EMIT for
-the simulation of an antenna.
-"""
-###############################################################################
-# Perform required inputs
-# ~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+# # EMIT: Antenna
+#
+# This example shows how to create a project in EMIT for
+# the simulation of an antenna using HFSS.
+#
+#
+
+# ## Perform required inputs
#
-# sphinx_gallery_thumbnail_path = "Resources/emit_simple_cosite.png"
+# Perform required imports.
import os
import pyaedt
+import tempfile
from pyaedt.emit_core.emit_constants import TxRxMode, ResultType
-###############################################################################
-# Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The ``NewThread`` Boolean variable defines whether to create a new instance
@@ -29,19 +27,19 @@
desktop_version = "2023.2"
-###############################################################################
-# Launch AEDT with EMIT
-# ~~~~~~~~~~~~~~~~~~~~~
-# Launch AEDT with EMIT. The ``Desktop`` class initializes AEDT and starts it
-# on the specified version and in the specified graphical mode.
+# ## Launch AEDT with EMIT
+#
+# Launch AEDT with EMIT. The ``launch_desktop()`` method initializes AEDT
+# using the specified version. The 2nd argument can be set to ``True`` to
+# run AEDT in non-graphical mode.
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
d = pyaedt.launch_desktop(desktop_version, non_graphical, NewThread)
-aedtapp = pyaedt.Emit(pyaedt.generate_unique_project_name())
+aedtapp = pyaedt.Emit(os.path.join(temp_dir.name, "antenna_cosite"))
-###############################################################################
-# Create and connect EMIT components
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Create and connect EMIT components
+#
# Create three radios and connect an antenna to each one.
rad1 = aedtapp.modeler.components.create_component("New Radio")
@@ -49,20 +47,25 @@
if rad1 and ant1:
ant1.move_and_connect_to(rad1)
-# Convenience method to create a radio and antenna connected together
+# ## Place Antenna Radio Pairs
+#
+# The method ``create_radio_antenna()`` places radio/antenna pair. The first
+# argument is the type of radio. The 2nd argumnt is the name that
+# will be assigned to the radio.
+
rad2, ant2 = aedtapp.modeler.components.create_radio_antenna("GPS Receiver")
rad3, ant3 = aedtapp.modeler.components.create_radio_antenna("Bluetooth Low Energy (LE)", "Bluetooth")
-###############################################################################
-# Define coupling among RF systems
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Define the coupling among the RF systems. This portion of the EMIT API is not
-# yet implemented.
+# ## Define the RF Environment
+#
+# The next step in this workflow is to specify the RF coupling among antennas.
+# This functionality yet to be implemented in the API, but can be entered from the UI.
+#
+#
-###############################################################################
-# Run EMIT simulation
-# ~~~~~~~~~~~~~~~~~~~
+# ## Run EMIT simulation
+#
# Run the EMIT simulation.
#
# This part of the example requires Ansys AEDT 2023 R2.
@@ -80,12 +83,16 @@
emi = worst.get_value(ResultType.EMI)
print("Worst case interference is: {} dB".format(emi))
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save project and close AEDT
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.force_close_desktop` method.
+# `pyaedt.Desktop.force_close_desktop` method.
# All methods provide for saving the project before closing.
aedtapp.save_project()
aedtapp.release_desktop(close_projects=True, close_desktop=True)
+
+# Clean up the temporary directory and remove the project files located
+# in ``temp_dir.name``.
+
+temp_dir.cleanup()
diff --git a/examples/07-EMIT/EMIT_HFSS_Example.py b/examples/07-EMIT/EMIT_HFSS_Example.py
index 840d5b96f56..a4726ee1671 100644
--- a/examples/07-EMIT/EMIT_HFSS_Example.py
+++ b/examples/07-EMIT/EMIT_HFSS_Example.py
@@ -1,116 +1,104 @@
-"""
-EMIT: HFSS to EMIT coupling
----------------------------
-This example shows how you can use PyAEDT to open an AEDT project with
-an HFSS design, create an EMIT design in the project, and link the HFSS design
-as a coupling link in the EMIT design.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
+# # EMIT: HFSS to EMIT coupling
+#
+# This example
+# demonstrates how link an HFSS design
+# to EMIT and model RF interference among various components.
#
-# sphinx_gallery_thumbnail_path = "Resources/emit_hfss.png"
+# > **Note:** This example uses the ``Cell Phone RFI Desense``
+# > project that is available with the AEDT installation in the
+# > folder ``\Examples\EMIT\``
-import os
+# ## Perform required imports
+#
+# Perform required imports.
-# Import required modules
+import os
import pyaedt
-from pyaedt.generic.filesystem import Scratch
+import tempfile
from pyaedt.emit_core.emit_constants import TxRxMode, ResultType
+import shutil
-###############################################################################
-## Set non-graphical mode
-# ~~~~~~~~~~~~~~~~~~~~~~~
+# ## Set non-graphical mode
+#
# Set non-graphical mode.
# You can set ``non_graphical`` either to ``True`` or ``False``.
# The Boolean parameter ``new_thread`` defines whether to create a new instance
# of AEDT or try to connect to an existing instance of it.
-#
-# The following code uses AEDT 2023 R2.
non_graphical = False
NewThread = True
desktop_version = "2023.2"
-scratch_path = pyaedt.generate_unique_folder_name()
-###############################################################################
-# Launch AEDT with EMIT
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Launch AEDT with EMIT
+#
# Launch AEDT with EMIT. The ``Desktop`` class initializes AEDT and starts it
# on the specified version and in the specified graphical mode.
+# A temporary working directory is created using ``tempfile``.
d = pyaedt.launch_desktop(desktop_version, non_graphical, NewThread)
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
+
+# ## Copy Example Files
+#
+# Copy the ``Cell Phone RFT Defense`` example data from the
+# installed examples folder to the temporary working
+# directory.
+#
+# > **Note:** The HFSS design from the installed example
+# > used to model the RF environment
+# > has been pre-solved. Hence, the results folder is copied and
+# > the RF interference between transcievers is calculated in EMIT using
+# > results from the linked HFSS design.
+#
+# The following lambda functions help create file and folder
+# names when copying data from the Examples folder.
-temp_folder = os.path.join(scratch_path, ("EmitHFSSExample"))
-if not os.path.exists(temp_folder):
- os.mkdir(temp_folder)
+file_name = lambda s: s + ".aedt"
+results_name = lambda s: s + ".aedtresults"
+pdf_name = lambda s: s + " Example.pdf"
-example_name = "Cell Phone RFI Desense"
-example_aedt = example_name + ".aedt"
-example_results = example_name + ".aedtresults"
-example_lock = example_aedt + ".lock"
-example_pdf_file = example_name + " Example.pdf"
+# Build the names of the source files for this example.
+example = "Cell Phone RFI Desense"
example_dir = os.path.join(d.install_path, "Examples\\EMIT")
-example_project = os.path.join(example_dir, example_aedt)
-example_results_folder = os.path.join(example_dir, example_results)
-example_pdf = os.path.join(example_dir, example_pdf_file)
-
-########################################################################################################
-# If the ``Cell Phone RFT Defense`` example is not
-# in the installation directory, exit from this example.
-
-if not os.path.exists(example_project):
- msg = """
- Cell phone RFT Desense example file is not in the
- Examples/EMIT directory under the EDT installation. You cannot run this example.
- """
- print(msg)
- d.release_desktop(True, True)
- exit()
-
-my_project = os.path.join(temp_folder, example_aedt)
-my_results_folder = os.path.join(temp_folder, example_results)
-my_project_lock = os.path.join(temp_folder, example_lock)
-my_project_pdf = os.path.join(temp_folder, example_pdf_file)
-
-if os.path.exists(my_project):
- os.remove(my_project)
-
-if os.path.exists(my_project_lock):
- os.remove(my_project_lock)
-
-with Scratch(scratch_path) as local_scratch:
- local_scratch.copyfile(example_project, my_project)
- local_scratch.copyfolder(example_results_folder, my_results_folder)
- if os.path.exists(example_pdf):
- local_scratch.copyfile(example_pdf, my_project_pdf)
-
-aedtapp = pyaedt.Emit(my_project)
-
-###############################################################################
-# Create and connect EMIT components
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+example_project = os.path.join(example_dir, file_name(example))
+example_results_folder = os.path.join(example_dir, results_name(example))
+example_pdf = os.path.join(example_dir, pdf_name(example))
+
+# Copy the files to the temporary working directory.
+
+project_name = shutil.copyfile(example_project,
+ os.path.join(temp_dir.name, file_name(example)))
+results_folder = shutil.copytree(example_results_folder,
+ os.path.join(temp_dir.name, results_name(example)))
+project_pdf = shutil.copyfile(example_pdf,
+ os.path.join(temp_dir.name, pdf_name(example)))
+
+# Open the project in the working directory.
+
+aedtapp = pyaedt.Emit(project_name)
+
+# ## Create and connect EMIT components
+#
# Create two radios with antennas connected to each one.
rad1, ant1 = aedtapp.modeler.components.create_radio_antenna("Bluetooth Low Energy (LE)")
rad2, ant2 = aedtapp.modeler.components.create_radio_antenna("Bluetooth Low Energy (LE)")
-###############################################################################
-# Define coupling among RF systems
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Define coupling among RF systems
+#
# Define coupling among the RF systems.
for link in aedtapp.couplings.linkable_design_names:
aedtapp.couplings.add_link(link)
+ print("linked \"" + link + "\".")
for link in aedtapp.couplings.coupling_names:
aedtapp.couplings.update_link(link)
+ print("linked \"" + link + "\".")
-###############################################################################
-# Run EMIT simulation
-# ~~~~~~~~~~~~~~~~~~~
+# ## Calculate RF Interference
+#
# Run the EMIT simulation. This portion of the EMIT API is not yet implemented.
#
# This part of the example requires Ansys AEDT 2023 R2.
@@ -128,12 +116,13 @@
emi = worst.get_value(ResultType.EMI)
print("Worst case interference is: {} dB".format(emi))
-###############################################################################
-# Save project and close AEDT
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Save and Close the Project
+#
# After the simulation completes, you can close AEDT or release it using the
-# :func:`pyaedt.Desktop.force_close_desktop` method.
+# `pyaedt.Desktop.force_close_desktop` method.
# All methods provide for saving the project before closing.
aedtapp.save_project()
aedtapp.release_desktop(close_projects=True, close_desktop=True)
+
+temp_dir.cleanup() # Remove temporary project files.
diff --git a/examples/07-EMIT/_static/coupling.png b/examples/07-EMIT/_static/coupling.png
new file mode 100644
index 00000000000..865600ccd78
Binary files /dev/null and b/examples/07-EMIT/_static/coupling.png differ
diff --git a/doc/source/Resources/emit_hfss.png b/examples/07-EMIT/_static/emit_hfss.png
similarity index 100%
rename from doc/source/Resources/emit_hfss.png
rename to examples/07-EMIT/_static/emit_hfss.png
diff --git a/doc/source/Resources/emit_simple_cosite.png b/examples/07-EMIT/_static/emit_simple_cosite.png
similarity index 100%
rename from doc/source/Resources/emit_simple_cosite.png
rename to examples/07-EMIT/_static/emit_simple_cosite.png
diff --git a/examples/07-EMIT/Readme.txt b/examples/07-EMIT/index.rst
similarity index 52%
rename from examples/07-EMIT/Readme.txt
rename to examples/07-EMIT/index.rst
index 35b36f1cd11..0453065f357 100644
--- a/examples/07-EMIT/Readme.txt
+++ b/examples/07-EMIT/index.rst
@@ -3,3 +3,10 @@ EMIT examples
These examples use PyAEDT to show some end-to-end workflows for EMIT.
This includes schematic generation, setup, and postprocessing.
+.. nbgallery::
+
+ ComputeInterferenceType.py
+ ComputeProtectionLevels.py
+ EMIT_Example.py
+ EMIT_HFSS_Example.py
+ interference_gui.py
\ No newline at end of file
diff --git a/examples/07-EMIT/interference_gui.py b/examples/07-EMIT/interference_gui.py
index cea3dfd1165..5ca3cb4a977 100644
--- a/examples/07-EMIT/interference_gui.py
+++ b/examples/07-EMIT/interference_gui.py
@@ -1,13 +1,11 @@
-"""
-EMIT: Classify interference type GUI
-----------------------------------------
-This example uses a GUI to open an AEDT project with
-an EMIT design and analyze the results to classify the
-worst-case interference.
-"""
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # EMIT: Classify interference type GUI
+#
+# This example uses a GUI to open an AEDT project with
+# an EMIT design and analyze the results to classify the
+# worst-case interference.
+#
+# > **Note:** This example requires EMIT Version 2023.2 or newer.
+
# Perform required imports.
import sys
@@ -19,40 +17,45 @@
import subprocess
import pyaedt.generic.constants as consts
-# Check that emit is a compatible version
-emitapp_desktop_version = "2023.2"
-if emitapp_desktop_version < "2023.2":
- print("Must have v2023.2 or later")
- sys.exit()
+# Check to see which Python libraries have been installed.
+# PySide6 and openpyxl will be installed if they are not found. An internet connection
+# is required to install missing packages.
-# Check to see which Python libraries have been installed
+# +
reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
installed_packages = [r.decode().split('==')[0] for r in reqs.split()]
-# Install required packages if they are not installed
def install(package):
subprocess.check_call([sys.executable, '-m', 'pip', 'install', package])
-# Install required libraries for GUI and Excel exporting (internet connection needed)
required_packages = ['PySide6', 'openpyxl']
for package in required_packages:
if package not in installed_packages:
install(package)
+# -
# Import PySide6 and openpyxl libraries
+
+
from PySide6 import QtWidgets, QtUiTools, QtGui, QtCore
from openpyxl.styles import PatternFill
import openpyxl
+
+# +
# Uncomment if there are Qt plugin errors
# import PySide6
# dirname = os.path.dirname(PySide6.__file__)
# plugin_path = os.path.join(dirname, 'plugins', 'platforms')
# os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = plugin_path
+# -
# Launch EMIT
+
+# +
non_graphical = False
new_thread = True
+emitapp_desktop_version = "2023.2"
desktop = pyaedt.launch_desktop(emitapp_desktop_version, non_graphical, new_thread)
# Add emitapi to system path
@@ -64,6 +67,11 @@ def install(package):
# Define .ui file for GUI
ui_file = pyaedt.downloads.download_file("emit", "interference_gui.ui")
Ui_MainWindow, _ = QtUiTools.loadUiType(ui_file)
+# -
+
+# ### Create a simpl QT UI
+#
+# Build a simple UI using QT.
class DoubleDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, decimals, values, max_power, min_power):
@@ -104,25 +112,24 @@ def __init__(self):
self.setupUi(self)
self.setup_widgets()
- ###############################################################################
- # Setup widgets
- # ~~~~~~~~~~~~~
- # Define all widgets from the UI file, connect the widgets to functions, define
- # table colors, and format table settings.
-
- def setup_widgets(self):
+# ## Setup widgets
+#
+# Define all widgets from the UI file, connect the widgets to functions, define
+# table colors, and format table settings.
+
+ def setup_widgets(self):
# Widget definitions for file selection/tab management
self.file_select_btn = self.findChild(QtWidgets.QToolButton, "file_select_btn")
self.file_path_box = self.findChild(QtWidgets.QLineEdit, "file_path_box")
self.design_name_dropdown = self.findChild(QtWidgets.QComboBox, "design_name_dropdown")
self.design_name_dropdown.setEnabled(True)
self.tab_widget = self.findChild(QtWidgets.QTabWidget, "tab_widget")
-
+
# Widget definitions for protection level classification
self.protection_results_btn = self.findChild(QtWidgets.QPushButton, "protection_results_btn")
self.protection_matrix = self.findChild(QtWidgets.QTableWidget, "protection_matrix")
self.protection_legend_table = self.findChild(QtWidgets.QTableWidget, "protection_legend_table")
-
+
self.damage_check = self.findChild(QtWidgets.QCheckBox, "damage_check")
self.overload_check = self.findChild(QtWidgets.QCheckBox, "overload_check")
self.intermodulation_check = self.findChild(QtWidgets.QCheckBox, "intermodulation_check")
@@ -131,7 +138,7 @@ def setup_widgets(self):
self.radio_specific_levels = self.findChild(QtWidgets.QCheckBox, "radio_specific_levels")
self.radio_dropdown = self.findChild(QtWidgets.QComboBox, "radio_dropdown")
self.protection_save_img_btn = self.findChild(QtWidgets.QPushButton, 'protection_save_img_btn')
-
+
# warning label
self.warning_label = self.findChild(QtWidgets.QLabel, "warnings")
myFont = QtGui.QFont()
@@ -139,7 +146,7 @@ def setup_widgets(self):
self.warning_label.setFont(myFont)
self.warning_label.setHidden(True)
self.design_name_dropdown.currentIndexChanged.connect(self.design_dropdown_changed)
-
+
# Setup for protection level buttons and table
self.protection_results_btn.setEnabled(False)
self.protection_export_btn.setEnabled(False)
@@ -162,18 +169,18 @@ def setup_widgets(self):
self.radio_dropdown.currentIndexChanged.connect(self.radio_dropdown_changed)
self.protection_legend_table.itemChanged.connect(self.table_changed)
self.protection_save_img_btn.clicked.connect(self.save_image)
-
+
# Widget definitions for interference type
self.interference_results_btn = self.findChild(QtWidgets.QPushButton, "interference_results_btn")
self.interference_matrix = self.findChild(QtWidgets.QTableWidget, "interference_matrix")
self.interference_legend_table = self.findChild(QtWidgets.QTableWidget, "interference_legend_table")
-
+
# set the items read only
for i in range(0, self.interference_legend_table.rowCount()):
item = self.interference_legend_table.item(i, 0)
item.setFlags(QtCore.Qt.ItemIsEnabled)
self.interference_legend_table.setItem(i, 0, item)
-
+
self.in_in_check = self.findChild(QtWidgets.QCheckBox, "in_in_check")
self.in_out_check = self.findChild(QtWidgets.QCheckBox, "in_out_check")
self.out_in_check = self.findChild(QtWidgets.QCheckBox, "out_in_check")
@@ -195,7 +202,7 @@ def setup_widgets(self):
self.out_out_check.stateChanged.connect(self.interference_results)
self.radio_specific_levels.stateChanged.connect(self.radio_specific)
self.interference_save_img_btn.clicked.connect(self.save_image)
-
+
# Color definition dictionary and previous project/design names
self.color_dict = {"green": [QtGui.QColor(125, 115, 202),'#7d73ca'],
"yellow":[QtGui.QColor(211, 89, 162), '#d359a2'],
@@ -204,49 +211,49 @@ def setup_widgets(self):
"white": [QtGui.QColor("white"),'#ffffff']}
self.previous_design = ''
self.previous_project = ''
-
+
# Set the legend tables to strech resize mode
header = self.protection_legend_table.horizontalHeader()
v_header = self.protection_legend_table.verticalHeader()
-
+
header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeMode.Stretch)
-
+
header = self.interference_legend_table.horizontalHeader()
v_header = self.interference_legend_table.verticalHeader()
-
+
header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeMode.Stretch)
v_header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeMode.Stretch)
-
+
# Input validation for protection level legend table
self.delegate = DoubleDelegate(decimals=2, values=values,
max_power=1000, min_power=-200)
self.protection_legend_table.setItemDelegateForColumn(0, self.delegate)
self.open_file_dialog()
+
- ###############################################################################
- # Open file dialog and select project
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Open the file dialog for project selection and populate the design dropdown
- # with all EMIT designs in the project.
+# ### Open File Dialog
+#
+# Open the file dialog for project selection and populate the design dropdown
+# with all EMIT designs in the project.
def open_file_dialog(self):
fname, _filter = QtWidgets.QFileDialog.getOpenFileName(self, "Select EMIT Project", "", "Ansys Electronics Desktop Files (*.aedt)", )
if fname:
self.file_path_box.setText(fname)
-
+
# Close previous project and open specified one
if self.emitapp is not None:
self.emitapp.close_project()
self.emitapp = None
desktop_proj = desktop.load_project(self.file_path_box.text())
-
+
# check for an empty project (i.e. no designs)
if isinstance(desktop_proj, bool):
self.file_path_box.setText("")
@@ -257,7 +264,7 @@ def open_file_dialog(self):
"one EMIT design. See AEDT log for more information.")
x = msg.exec()
return
-
+
# Check if project is already open
if desktop_proj.lock_file == None:
msg = QtWidgets.QMessageBox()
@@ -276,7 +283,7 @@ def open_file_dialog(self):
design_type = desktop.design_type(desktop_proj.project_name, d)
if design_type == "EMIT":
emit_designs.append(d)
-
+
# add warning if no EMIT design
# Note: this should never happen since loading a project without an EMIT design
# should add a blank EMIT design
@@ -285,20 +292,20 @@ def open_file_dialog(self):
self.warning_label.setText("Warning: The project must contain at least one EMIT design.")
self.warning_label.setHidden(False)
return
-
+
self.populating_dropdown = True
self.design_name_dropdown.addItems(emit_designs)
self.populating_dropdown = False
self.emitapp = get_pyaedt_app(desktop_proj.project_name, emit_designs[0])
self.design_name_dropdown.setCurrentIndex(0)
-
+
# check for at least 2 radios
radios = self.emitapp.modeler.components.get_radios()
self.warning_label.setHidden(True)
if len(radios) < 2:
self.warning_label.setText("Warning: The selected design must contain at least two radios.")
self.warning_label.setHidden(False)
-
+
if self.radio_specific_levels.isEnabled():
self.radio_specific_levels.setChecked(False)
self.radio_dropdown.clear()
@@ -306,15 +313,14 @@ def open_file_dialog(self):
self.protection_levels = {}
values = [float(self.protection_legend_table.item(row, 0).text()) for row in range(self.protection_legend_table.rowCount())]
self.protection_levels['Global'] = values
-
+
self.radio_specific_levels.setEnabled(True)
self.protection_results_btn.setEnabled(True)
self.interference_results_btn.setEnabled(True)
- ###############################################################################
- # Change design selection
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Refresh the warning messages when the selected design changes
+# ### Change design selection
+#
+# Refresh the warning messages when the selected design changes
def design_dropdown_changed(self):
if self.populating_dropdown:
@@ -332,11 +338,10 @@ def design_dropdown_changed(self):
# clear the table if the design is changed
self.clear_table()
- ###############################################################################
- # Enable radio specific protection levels
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Activate radio selection dropdown and initialize dictionary to store protection levels
- # when the radio-specific level dropdown is checked.
+# ### Enable radio specific protection levels
+#
+# Activate radio selection dropdown and initialize dictionary to store protection levels
+# when the radio-specific level dropdown is checked.
def radio_specific(self):
self.radio_dropdown.setEnabled(self.radio_specific_levels.isChecked())
@@ -354,11 +359,11 @@ def radio_specific(self):
values = [float(self.protection_legend_table.item(row, 0).text()) for row in range(self.protection_legend_table.rowCount())]
self.protection_levels['Global'] = values
self.global_protection_level = not self.radio_specific_levels.isChecked()
-
- ###############################################################################
- # Update legend table
- # ~~~~~~~~~~~~~~~~~~~
- # Update shown legend table values when the radio dropdown value changes.
+
+
+# ### Update legend table
+#
+# Update shown legend table values when the radio dropdown value changes.
def radio_dropdown_changed(self):
if self.radio_dropdown.isEnabled():
@@ -372,11 +377,10 @@ def radio_dropdown_changed(self):
range(self.protection_legend_table.rowCount())]
self.delegate.update_values(values)
- ###############################################################################
- # Save legend table values
- # ~~~~~~~~~~~~~~~~~~~~~~~~
- # Save inputted radio protection level threshold values every time one is changed
- # in the legend table.
+# ### Save legend table values
+#
+# Save inputted radio protection level threshold values every time one is changed
+# in the legend table.
def table_changed(self):
if self.changing == False:
@@ -389,10 +393,9 @@ def table_changed(self):
self.protection_levels[index] = values
self.delegate.update_values(values)
- ###############################################################################
- # Save scenario matrix to as PNG file
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Save the scenario matrix table as a PNG file.
+# ### Save scenario matrix to as PNG file
+#
+# Save the scenario matrix table as a PNG file.
def save_image(self):
if self.tab_widget.currentIndex() == 0:
@@ -406,10 +409,9 @@ def save_image(self):
table.render(image)
image.save(fname)
- ###############################################################################
- # Save scenario matrix to Excel file
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Write the scenario matrix results to an Excel file with color coding.
+# ### Save scenario matrix to Excel file
+#
+# Write the scenario matrix results to an Excel file with color coding.
def save_results_excel(self):
defaultName = ""
@@ -439,10 +441,9 @@ def save_results_excel(self):
fill_type = "solid")
workbook.save(fname)
- ###############################################################################
- # Run interference type simulation
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Run interference type simulation and classify results.
+# ### Run interference type simulation
+#
+# Run interference type simulation and classify results.
def interference_results(self):
# Initialize filter check marks and expected filter results
@@ -479,11 +480,12 @@ def interference_results(self):
if self.tx_radios is None or self.rx_radios is None:
return
- # Classify the interference
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Iterate over all the transmitters and receivers and compute the power
- # at the input to each receiver due to each of the transmitters. Compute
- # which, if any, type of interference occurred.
+# ### Classify the interference
+#
+# Iterate over all the transmitters and receivers and compute the power
+# at the input to each receiver due to each of the transmitters. Compute
+# which, if any, type of interference occurred.
+
domain = self.emitapp.results.interaction_domain()
self.all_colors, self.power_matrix = self.rev.interference_type_classification(domain, use_filter = True, filter_list = filter)
@@ -491,11 +493,10 @@ def interference_results(self):
self.emitapp.save_project()
self.populate_table()
- ###############################################################################
- # Run protection level simulation
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Run protection level simulation and classify results accroding to inputted
- # threshold levels.
+# ### Run protection level simulation
+#
+# Run protection level simulation and classify results accroding to inputted
+# threshold levels.
def protection_results(self):
# Initialize filter check marks and expected filter results
@@ -538,12 +539,11 @@ def protection_results(self):
filter_list = filter)
self.populate_table()
-
- ###############################################################################
- # Populate the scenario matrix
- # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- # Create a scenario matrix view with the transmitters defined across the top
- # and receivers down the left-most column.
+
+# ### Populate the scenario matrix
+#
+# Create a scenario matrix view with the transmitters defined across the top
+# and receivers down the left-most column.
def populate_table(self):
if self.tab_widget.currentIndex() == 0:
@@ -591,10 +591,10 @@ def clear_table(self):
table.setColumnCount(0)
table.setRowCount(0)
- ###############################################################################
- # GUI closing event
- # ~~~~~~~~~~~~~~~~~
- # Close AEDT if the GUI is closed.
+# ### GUI closing event
+#
+# Close AEDT if the GUI is closed.
+
def closeEvent(self, event):
msg = QtWidgets.QMessageBox()
msg.setWindowTitle("Closing GUI")
@@ -606,9 +606,8 @@ def closeEvent(self, event):
else:
desktop.release_desktop(True, True)
-###############################################################################
-# Run GUI
-# ~~~~~~~
+# ### Run GUI
+#
# Launch the GUI. If you want to run the GUI, uncomment the ``window.show()`` and
# ``app.exec_()`` method calls.
diff --git a/examples/07-TwinBuilder/01-RC_Circuit_Example.py b/examples/07-TwinBuilder/01-RC_Circuit_Example.py
deleted file mode 100644
index 42b842b459a..00000000000
--- a/examples/07-TwinBuilder/01-RC_Circuit_Example.py
+++ /dev/null
@@ -1,107 +0,0 @@
-"""
-Twin Builder: RC circuit design anaysis
----------------------------------------
-This example shows how you can use PyAEDT to create a Twin Builder design
-and run a Twin Builder time-domain simulation.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
-# Perform required imports.
-
-import pyaedt
-
-###############################################################################
-# Select version and set launch options
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Select the Twin Builder version and set the launch options. The following code
-# launches Twin Builder 2023 R2 in graphical mode.
-#
-# You can change the Boolean parameter ``non_graphical`` to ``True`` to launch
-# Twin Builder in non-graphical mode. You can also change the Boolean parameter
-# ``new_thread`` to ``False`` to launch Twin Builder in an existing AEDT session
-# if one is running.
-
-desktop_version = "2023.2"
-
-non_graphical = False
-new_thread = True
-
-###############################################################################
-# Launch Twin Builder
-# ~~~~~~~~~~~~~~~~~~~
-# Launch Twin Builder using an implicit declaration and add a new design with
-# a default setup.
-
-tb = pyaedt.TwinBuilder(projectname=pyaedt.generate_unique_project_name(),
- specified_version=desktop_version,
- non_graphical=non_graphical,
- new_desktop_session=new_thread
- )
-tb.modeler.schematic_units = "mil"
-
-###############################################################################
-# Create components for RC circuit
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create components for an RC circuit driven by a pulse voltage source.
-# Create components, such as a voltage source, resistor, and capacitor.
-
-source = tb.modeler.schematic.create_voltage_source("E1", "EPULSE", 10, 10, [0, 0])
-resistor = tb.modeler.schematic.create_resistor("R1", 10000, [1000, 1000], 90)
-capacitor = tb.modeler.schematic.create_capacitor("C1", 1e-6, [2000, 0])
-
-###############################################################################
-# Create ground
-# ~~~~~~~~~~~~~
-# Create a ground, which is needed for an analog analysis.
-
-gnd = tb.modeler.components.create_gnd([0, -1000])
-
-###############################################################################
-# Connect components
-# ~~~~~~~~~~~~~~~~~~
-# Connects components with pins.
-
-source.pins[1].connect_to_component(resistor.pins[0])
-resistor.pins[1].connect_to_component(capacitor.pins[0])
-capacitor.pins[1].connect_to_component(source.pins[0])
-source.pins[0].connect_to_component(gnd.pins[0])
-
-###############################################################################
-# Parametrize transient setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Parametrize the default transient setup by setting the end time.
-
-tb.set_end_time("300ms")
-
-###############################################################################
-# Solve transient setup
-# ~~~~~~~~~~~~~~~~~~~~~
-# Solve the transient setup.
-
-tb.analyze_setup("TR")
-
-
-###############################################################################
-# Get report data and plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Get report data and plot it using Matplotlib. The following code gets and plots
-# the values for the voltage on the pulse voltage source and the values for the
-# voltage on the capacitor in the RC circuit.
-
-E_Value = "E1.V"
-C_Value = "C1.V"
-
-x = tb.post.get_solution_data([E_Value, C_Value], "TR", "Time")
-x.plot([E_Value, C_Value], xlabel="Time", ylabel="Capacitor Voltage vs Input Pulse")
-
-tb.save_project()
-
-###############################################################################
-# Close Twin Builder
-# ~~~~~~~~~~~~~~~~~~
-# After the simulation completes, you can close Twin Builder or release it.
-# All methods provide for saving the project before closing.
-
-tb.release_desktop()
diff --git a/examples/07-TwinBuilder/02-Wiring_A_Rectifier.py b/examples/07-TwinBuilder/02-Wiring_A_Rectifier.py
index bd7b1b45469..f226aea4aec 100644
--- a/examples/07-TwinBuilder/02-Wiring_A_Rectifier.py
+++ b/examples/07-TwinBuilder/02-Wiring_A_Rectifier.py
@@ -1,22 +1,22 @@
-"""
-Twin Builder: wiring a rectifier with a capacitor filter
----------------------------------------------------------
-This example shows how you can use PyAEDT to create a Twin Builder design
-and run a Twin Builder time-domain simulation.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Twin Builder: wiring a rectifier with a capacitor filter
+#
+# This example shows how you can use PyAEDT to create a Twin Builder design
+# and run a Twin Builder time-domain simulation.
+#
+#
+
+# ## Perform required imports
+#
# Perform required imports.
import math
import matplotlib.pyplot as plt
import pyaedt
+import tempfile
+import os
-###############################################################################
-# Select version and set launch options
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Select version and set launch options
+#
# Select the Twin Builder version and set the launch options. The following code
# launches Twin Builder 2023 R2 in graphical mode.
#
@@ -28,74 +28,75 @@
desktop_version = "2023.2"
non_graphical = False
new_thread = True
+temp_dir = tempfile.TemporaryDirectory(suffix=".ansys")
-###############################################################################
-# Launch Twin Builder
-# ~~~~~~~~~~~~~~~~~~~
+# ## Launch Twin Builder
+#
# Launch Twin Builder using an implicit declaration and add a new design with
# a default setup.
-tb = pyaedt.TwinBuilder(projectname=pyaedt.generate_unique_project_name(),
+tb = pyaedt.TwinBuilder(projectname=os.path.join(temp_dir.name, "TB_Rectifier_Demo"),
specified_version=desktop_version,
non_graphical=non_graphical,
new_desktop_session=new_thread
)
-###############################################################################
-# Create components for bridge rectifier
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Create components for a bridge rectifier with a capacitor filter.
-
-# Define the grid distance for ease in calculations.
+# ## Create components for bridge rectifier
+#
+# Place components for a bridge rectifier and a capacitor filter in the schematic editor.
+#
+# Specify the grid spacing to use for placement
+# of components in the schematic editor. Components are placed using the named
+# argument ``location`` as a list of ``[x, y]`` values in mm.
G = 0.00254
-# Create an AC sinosoidal source component.
+# Create an AC sinosoidal voltage source.
-source = tb.modeler.schematic.create_voltage_source("V_AC", "ESINE", 100, 50, [-1 * G, 0])
+source = tb.modeler.schematic.create_voltage_source("V_AC", "ESINE", 100, 50, location=[-1 * G, 0])
-# Create the four diodes of the bridge rectifier.
+# Place the four diodes of the bridge rectifier. The named argument ``angle`` is the rotation angle
+# of the component in radians.
diode1 = tb.modeler.schematic.create_diode(compname="D1", location=[10 * G, 6 * G], angle=3 * math.pi / 2)
diode2 = tb.modeler.schematic.create_diode(compname="D2", location=[20 * G, 6 * G], angle=3 * math.pi / 2)
diode3 = tb.modeler.schematic.create_diode(compname="D3", location=[10 * G, -4 * G], angle=3 * math.pi / 2)
diode4 = tb.modeler.schematic.create_diode(compname="D4", location=[20 * G, -4 * G], angle=3 * math.pi / 2)
-# Create a capacitor filter.
+# Place a capacitor filter.
capacitor = tb.modeler.schematic.create_capacitor(compname="C_FILTER", value=1e-6, location=[29 * G, -10 * G])
-# Create a load resistor.
+# Place a load resistor.
resistor = tb.modeler.schematic.create_resistor(compname="RL", value=100000, location=[39 * G, -10 * G])
-# Create a ground.
+# Place the ground component.
gnd = tb.modeler.components.create_gnd(location=[5 * G, -16 * G])
-###############################################################################
-# Connect components
-# ~~~~~~~~~~~~~~~~~~
+# ## Connect components
+#
# Connect components with wires.
-# Wire the diode bridge.
+# Connect the diode pins to create the bridge.
tb.modeler.schematic.create_wire(points_array=[diode1.pins[0].location, diode3.pins[0].location])
tb.modeler.schematic.create_wire(points_array=[diode2.pins[1].location, diode4.pins[1].location])
tb.modeler.schematic.create_wire(points_array=[diode1.pins[1].location, diode2.pins[0].location])
tb.modeler.schematic.create_wire(points_array=[diode3.pins[1].location, diode4.pins[0].location])
-# Wire the AC source.
+# Connect the voltage source to the bridge.
tb.modeler.schematic.create_wire(points_array=[source.pins[1].location, [0, 10 * G], [15 * G, 10 * G], [15 * G, 5 * G]])
tb.modeler.schematic.create_wire(points_array=[source.pins[0].location, [0, -10 * G], [15 * G, -10 * G], [15 * G, -5 * G]])
-# Wire the filter capacitor and load resistor.
+# Connect the filter capacitor and load resistor.
tb.modeler.schematic.create_wire(points_array=[resistor.pins[0].location, [40 * G, 0], [22 * G, 0]])
tb.modeler.schematic.create_wire(points_array=[capacitor.pins[0].location, [30 * G, 0]])
-# Wire the ground.
+# Add the ground connection.
tb.modeler.schematic.create_wire(points_array=[resistor.pins[1].location, [40 * G, -15 * G], gnd.pins[0].location])
tb.modeler.schematic.create_wire(points_array=[capacitor.pins[1].location, [30 * G, -15 * G]])
@@ -104,45 +105,48 @@
# Zoom to fit the schematic
tb.modeler.zoom_to_fit()
-###############################################################################
-# Parametrize transient setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-# Parametrize the default transient setup by setting the end time.
+# The circuit schematic will now be visible in the Twin Builder schematic editor and should look like
+# the image shown at the beginning of the example.
+#
+# ## Run the Simulation
+#
+# Update the total time to be simulated and run the analysis
tb.set_end_time("100ms")
-
-###############################################################################
-# Solve transient setup
-# ~~~~~~~~~~~~~~~~~~~~~
-# Solve the transient setup.
-
tb.analyze_setup("TR")
-
-###############################################################################
-# Get report data and plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get report data and plot using Matplotlib
+#
# Get report data and plot it using Matplotlib. The following code gets and plots
# the values for the voltage on the pulse voltage source and the values for the
# voltage on the capacitor in the RC circuit.
-E_Value = "V_AC.V"
-x = tb.post.get_solution_data(E_Value, "TR", "Time")
-plt.plot(x.intrinsics["Time"], x.data_real(E_Value))
-
-R_Value = "RL.V"
-x = tb.post.get_solution_data(R_Value, "TR", "Time")
-plt.plot(x.intrinsics["Time"], x.data_real(R_Value))
+src_name = source.InstanceName + ".V"
+x = tb.post.get_solution_data(src_name, tb.analysis_setup, "Time")
+plt.plot(x.intrinsics["Time"], x.data_real(src_name))
+plt.grid()
+plt.xlabel("Time")
+plt.ylabel("AC Voltage")
+plt.show()
+r_voltage = resistor.InstanceName + ".V"
+x = tb.post.get_solution_data(r_voltage, tb.analysis_setup, "Time")
+plt.plot(x.intrinsics["Time"], x.data_real(r_voltage))
plt.grid()
plt.xlabel("Time")
plt.ylabel("AC to DC Conversion using Rectifier")
plt.show()
-###############################################################################
-# Close Twin Builder
-# ~~~~~~~~~~~~~~~~~~
+# ## Close Twin Builder
+#
# After the simulation is completed, you can close Twin Builder or release it.
# All methods provide for saving the project before closing.
tb.release_desktop()
+
+# ## Cleanup
+#
+# Remove the project and temporary folder. The project files can be retrieved from the
+# temporary directory, ``temp_dir.name``, prior to executing the following cell, if desired.
+
+temp_dir.cleanup() # Cleans up all files and removes the project directory.
diff --git a/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py b/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py
index 979bae7e9a8..840de7802e3 100644
--- a/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py
+++ b/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py
@@ -1,17 +1,14 @@
-"""
-Twin Builder: dynamic ROM creation and simulation (2023 R2 beta)
-----------------------------------------------------------------
-This example shows how you can use PyAEDT to create a dynamic ROM in Twin Builder
-and run a Twin Builder time-domain simulation.
-
-.. note::
- This example uses functionality only available in Twin Builder 2023 R2 and later.
- For 2023 R2, the build date must be 8/7/2022 or later.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Twin Builder: Dynamic ROM
+#
+# This example shows how you can use PyAEDT to create a dynamic ROM in Twin Builder
+# and run a Twin Builder time-domain simulation.
+#
+# > **Note:** This example uses functionality only available in Twin
+# > Builder 2023 R2 and later.
+
+
+# ## Perform required imports
+#
# Perform required imports.
import os
@@ -22,9 +19,9 @@
from pyaedt import generate_unique_folder_name
from pyaedt import downloads
from pyaedt import settings
-###############################################################################
-# Select version and set launch options
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# ## Select version and set launch options
+#
# Select the Twin Builder version and set launch options. The following code
# launches Twin Builder 2023 R2 in graphical mode.
#
@@ -37,9 +34,8 @@
non_graphical = False
new_thread = True
-###############################################################################
-# Set up input data
-# ~~~~~~~~~~~~~~~~~
+# ## Set up input data
+#
# Define needed file name
source_snapshot_data_zipfilename = "Ex1_Mechanical_DynamicRom.zip"
@@ -60,17 +56,25 @@
shutil.copyfile(os.path.join(source_data_folder ,source_build_conf_file), os.path.join(data_folder,source_build_conf_file))
-###############################################################################
-# Launch Twin Builder and build ROM component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch Twin Builder and build ROM component
+#
# Launch Twin Builder using an implicit declaration and add a new design with
# a default setup for building the dynamic ROM component.
tb = TwinBuilder(projectname=generate_unique_project_name(),specified_version=desktop_version, non_graphical=non_graphical, new_desktop_session=new_thread)
-# Switch the current desktop configuration and the schematic environment to "Twin Builder".
-# The Dynamic ROM feature is only available with a twin builder license.
-# This and the restoring section at the end are not needed if the desktop is already configured as "Twin Builder".
+# ## Desktop Configuration
+#
+# > **Note:** Only run following cell if AEDT is not configured to run _"Twin Builder"_.
+# >
+# > The following cell configures Electronics Desktop (AEDT) and the schematic editor
+# > to use the _"Twin Builder"_ confguration.
+# > The dynamic ROM feature is only available with a Twin Builder license.
+# > A cell at the end of this example restores the AEDT configuration. If your
+# > environment is set up
+# > to use the _"Twin Builder"_ configuration, you do not need to run these sections.
+# >
+
current_desktop_config = tb._odesktop.GetDesktopConfiguration()
current_schematic_environment = tb._odesktop.GetSchematicEnvironment()
tb._odesktop.SetDesktopConfiguration("Twin Builder")
@@ -95,11 +99,10 @@
rom_manager.CreateROMComponent(dynamic_rom_path.replace('\\', '/'),'dynarom')
-###############################################################################
-# Create schematic
-# ~~~~~~~~~~~~~~~~
+# ## Create schematic
+#
# Place components to create a schematic.
-
+
# Define the grid distance for ease in calculations
G = 0.00254
@@ -121,26 +124,23 @@
# Zoom to fit the schematic
tb.modeler.zoom_to_fit()
-###############################################################################
-# Parametrize transient setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Parametrize transient setup
+#
# Parametrize the default transient setup by setting the end time.
tb.set_end_time("1000s")
tb.set_hmin("1s")
tb.set_hmax("1s")
-###############################################################################
-# Solve transient setup
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Solve transient setup
+#
# Solve the transient setup.
tb.analyze_setup("TR")
-###############################################################################
-# Get report data and plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get report data and plot using Matplotlib
+#
# Get report data and plot it using Matplotlib. The following code gets and plots
# the values for the voltage on the pulse voltage source and the values for the
# output of the dynamic ROM.
@@ -159,9 +159,8 @@
plt.show()
-###############################################################################
-# Close Twin Builder
-# ~~~~~~~~~~~~~~~~~~
+# ## Close Twin Builder
+#
# After the simulation is completed, you can close Twin Builder or release it.
# All methods provide for saving the project before closing.
diff --git a/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py b/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py
index 10f78cc11a6..ab069e77ee1 100644
--- a/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py
+++ b/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py
@@ -1,17 +1,13 @@
-"""
-Twin Builder: static ROM creation and simulation (2023 R2 beta)
----------------------------------------------------------------
-This example shows how you can use PyAEDT to create a static ROM in Twin Builder
-and run a Twin Builder time-domain simulation.
-
-.. note::
- This example uses functionality only available in Twin Builder 2023 R2 and later.
- For 2023 R2, the build date must be 8/7/2022 or later.
-"""
-
-###############################################################################
-# Perform required imports
-# ~~~~~~~~~~~~~~~~~~~~~~~~
+# # Twin Builder: Static ROM
+#
+# This example shows how you can use PyAEDT to create a static ROM in Twin Builder
+# and run a Twin Builder time-domain simulation.
+#
+# > **Note:** This example uses functionality only
+# > available in Twin Builder 2023 R2 and later.
+
+# ## Perform required imports
+#
# Perform required imports.
import os
@@ -24,9 +20,8 @@
from pyaedt import downloads
from pyaedt import settings
-###############################################################################
-# Select version and set launch options
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Select version and set launch options
+#
# Select the Twin Builder version and set launch options. The following code
# launches Twin Builder 2023 R2 in graphical mode.
#
@@ -38,23 +33,26 @@
desktop_version = "2023.2"
non_graphical = False
new_thread = True
-###############################################################################
-# Set up input data
-# ~~~~~~~~~~~~~~~~~
-# Define needed file name
+
+# ## Set up input data
+#
+# The following files will be downloaded along with the
+# other project data used to run this example.
source_snapshot_data_zipfilename = "Ex1_Fluent_StaticRom.zip"
source_build_conf_file = "SROMbuild.conf"
source_props_conf_file = "SROM_props.conf"
-# Download data from example_data repository
+# ## Download Example Data
+#
+# The following cell downloads the required files needed to run this example and extracts them in a local folder ``"Ex04"``
+
+# +
source_data_folder = downloads.download_twin_builder_data(source_snapshot_data_zipfilename, True)
source_data_folder = downloads.download_twin_builder_data(source_build_conf_file, True)
source_data_folder = downloads.download_twin_builder_data(source_props_conf_file, True)
-# Uncomment the following line for local testing
-# source_data_folder = "D:\\Scratch\\TempStatic"
-
+# Target folder to extract project files.
data_folder = os.path.join(source_data_folder, "Ex04")
# Unzip training data and config file
@@ -63,24 +61,33 @@
os.path.join(data_folder, source_build_conf_file))
shutil.copyfile(os.path.join(source_data_folder, source_props_conf_file),
os.path.join(data_folder, source_props_conf_file))
+# -
-###############################################################################
-# Launch Twin Builder and build ROM component
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Launch Twin Builder and build ROM component
+#
# Launch Twin Builder using an implicit declaration and add a new design with
# a default setup for building the static ROM component.
tb = TwinBuilder(projectname=generate_unique_project_name(), specified_version=desktop_version,
non_graphical=non_graphical, new_desktop_session=new_thread)
-# Switch the current desktop configuration and the schematic environment to "Twin Builder".
-# The Static ROM feature is only available with a twin builder license.
-# This and the restoring section at the end are not needed if the desktop is already configured as "Twin Builder".
+# ## Desktop Configuration
+#
+# > **Note:** Only run following cell if AEDT is not configured to run _"Twin Builder"_.
+# >
+# > The following cell configures Electronics Desktop (AEDT) and the schematic editor
+# > to use the _"Twin Builder"_ confguration.
+# > The Static ROM feature is only available with a Twin Builder license.
+# > A cell at the end of this example restores the AEDT configuration. If your
+# > environment is set up
+# > to use the _"Twin Builder"_ configuration, you do not need to run these sections._
+
current_desktop_config = tb._odesktop.GetDesktopConfiguration()
current_schematic_environment = tb._odesktop.GetSchematicEnvironment()
tb._odesktop.SetDesktopConfiguration("Twin Builder")
tb._odesktop.SetSchematicEnvironment(1)
+# +
# Get the static ROM builder object
rom_manager = tb._odesign.GetROMManager()
static_rom_builder = rom_manager.GetStaticROMBuilder()
@@ -98,12 +105,13 @@
# Create the ROM component definition in Twin Builder
rom_manager.CreateROMComponent(static_rom_path.replace('\\', '/'), 'staticrom')
+# -
-###############################################################################
-# Create schematic
-# ~~~~~~~~~~~~~~~~
+# ## Create schematic
+#
# Place components to create a schematic.
+# +
# Define the grid distance for ease in calculations
G = 0.00254
@@ -113,6 +121,7 @@
# Place two excitation sources
source1 = tb.modeler.schematic.create_periodic_waveform_source(None, "SINE", 2.5, 0.01, 0, 7.5, 0, [20 * G, 29 * G])
source2 = tb.modeler.schematic.create_periodic_waveform_source(None, "SINE", 50, 0.02, 0, 450, 0, [20 * G, 25 * G])
+# -
# Connect components with wires
@@ -128,29 +137,28 @@
# Zoom to fit the schematic
tb.modeler.zoom_to_fit()
-###############################################################################
-# Parametrize transient setup
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Parametrize transient setup
+#
# Parametrize the default transient setup by setting the end time.
tb.set_end_time("300s")
tb.set_hmin("1s")
tb.set_hmax("1s")
-###############################################################################
-# Solve transient setup
-# ~~~~~~~~~~~~~~~~~~~~~
+# ## Solve transient setup
+#
# Solve the transient setup. Skipping in case of documentation build.
if os.getenv("PYAEDT_DOC_GENERATION", "False") != "1":
tb.analyze_setup("TR")
-###############################################################################
-# Get report data and plot using Matplotlib
-# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+# ## Get report data and plot using Matplotlib
+#
# Get report data and plot it using Matplotlib. The following code gets and plots
# the values for the voltage on the pulse voltage source and the values for the
# output of the dynamic ROM.
+
+
if os.getenv("PYAEDT_DOC_GENERATION", "False") != "1":
e_value = "ROM1.outfield_mode_1"
x = tb.post.get_solution_data(e_value, "TR", "Time")
@@ -166,9 +174,8 @@
x.plot()
-###############################################################################
-# Close Twin Builder
-# ~~~~~~~~~~~~~~~~~~
+# ## Close Twin Builder
+#
# After the simulation is completed, you can close Twin Builder or release it.
# All methods provide for saving the project before closing.
diff --git a/examples/07-TwinBuilder/Readme.txt b/examples/07-TwinBuilder/index.rst
similarity index 56%
rename from examples/07-TwinBuilder/Readme.txt
rename to examples/07-TwinBuilder/index.rst
index df697376902..b511feabf0c 100644
--- a/examples/07-TwinBuilder/Readme.txt
+++ b/examples/07-TwinBuilder/index.rst
@@ -2,3 +2,9 @@ Twin Builder examples
~~~~~~~~~~~~~~~~~~~~~
These examples use PyAEDT to show some end-to-end workflows for Twin Builder.
This includes schematic generation, setup, and postprocessing.
+
+.. nbgallery::
+
+ 02-Wiring_A_Rectifier.py
+ 03-Dynamic_ROM_Creation_And_Visualization.py
+ 04-Static_ROM_Creation_And_Visualization.py
diff --git a/examples/Readme.txt b/examples/index.rst
similarity index 77%
rename from examples/Readme.txt
rename to examples/index.rst
index 088894ba498..c67716ec568 100644
--- a/examples/Readme.txt
+++ b/examples/index.rst
@@ -1,4 +1,10 @@
-.. _ref_example_gallery:
+.. _ref_examples:
+
+.. toctree::
+ :hidden:
+ :maxdepth: 2
+
+ 00-EDB/index
Examples
========
diff --git a/pyaedt/modeler/circuits/object3dcircuit.py b/pyaedt/modeler/circuits/object3dcircuit.py
index a0843748611..cfad89c47e6 100644
--- a/pyaedt/modeler/circuits/object3dcircuit.py
+++ b/pyaedt/modeler/circuits/object3dcircuit.py
@@ -137,7 +137,7 @@ def connect_to_component(self, component_pin, page_name=None, use_wire=False, wi
Parameters
----------
- component_pin : :class:`pyaedt.modeler.circuits.PrimitivesNexxim.CircuitPins`
+ component_pin : :class:`pyaedt.modeler.circuits.objct3dcircuit.CircuitPins`
Component pin to attach.
page_name : str, optional
Page port name. The default value is ``None``, in which case
@@ -145,7 +145,8 @@ def connect_to_component(self, component_pin, page_name=None, use_wire=False, wi
use_wire : bool, optional
Whether to use wires or a page port to connect the pins.
The default is ``False``, in which case a page port is used. Note
- that if wires are used but not well placed, shorts can result.
+ that if wires are used but not well-placed, unintentional
+ short-circuits may result.
wire_name : str, optional
Wire name used only when user_wire is ``True``. Default value is ``""``.
clearance_units : int, optional
diff --git a/pyproject.toml b/pyproject.toml
index 05deddd2c00..1e44176a074 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -65,10 +65,12 @@ tests = [
"scikit-learn==1.3.1; python_version > '3.7'",
"SRTM.py",
"utm",
- "scikit-rf==0.31.0",
+ "scikit-rf",
+ "jsonschema",
]
doc = [
- "ansys-sphinx-theme==0.13.1",
+ "ansys-sphinx-theme==0.12.2",
+ "pydata-sphinx-theme==0.14.4",
"imageio==2.31.5",
"imageio-ffmpeg==0.4.9",
"ipython==8.13.0; python_version < '3.9'",
@@ -80,6 +82,7 @@ doc = [
"matplotlib==3.7.3; python_version == '3.8'",
"matplotlib==3.8.0; python_version > '3.8'",
"nbsphinx==0.9.3",
+ "jupytext==1.16.0",
"numpydoc==1.5.0; python_version == '3.7'",
"numpydoc==1.6.0; python_version > '3.7'",
"osmnx",
@@ -96,7 +99,6 @@ doc = [
"sphinx-autobuild==2021.3.14",
"sphinx-autodoc-typehints==1.24.0",
"sphinx-copybutton==0.5.2",
- "sphinx-gallery==0.14.0",
"sphinx-notfound-page==1.0.0",
"sphinxcontrib-websupport==1.2.4; python_version <= '3.9'",
"sphinxcontrib-websupport==1.2.5; python_version <= '3.7'",
@@ -146,6 +148,9 @@ all = [
"scikit-rf==0.31.0",
"openpyxl==3.1.2",
]
+ci = [
+ "pypandoc-binary",
+]
[tool.flit.module]
name = "pyaedt"
@@ -214,4 +219,4 @@ exclude = [
'\.Modeler3D\.create_choke$', # bad RT05
'\._unittest', # missing docstring for tests
'HistoryProps.', # bad RT05 because of the base class named OrderedDict
-]
+]
\ No newline at end of file