diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 32a1a601f9a..7270a15244c 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -73,7 +73,7 @@ jobs: # TODO: Update to ansys/actions/doc-build@v6 once we remove examples doc-build: - name: Documentation build without examples + name: Documentation build runs-on: ubuntu-latest needs: [doc-style] steps: @@ -91,7 +91,7 @@ jobs: - name: Install pyaedt and documentation dependencies run: | - pip install .[doc-no-examples] + pip install .[doc] - name: Retrieve PyAEDT version id: version @@ -105,119 +105,28 @@ jobs: sudo apt install graphviz texlive-latex-extra latexmk texlive-xetex texlive-fonts-extra -y # TODO: Update this step once pyaedt-examples is ready - - name: Build HTML documentation without examples + - name: Build HTML documentation run: | make -C doc clean - make -C doc html-no-examples + make -C doc html # Verify that sphinx generates no warnings - name: Check for warnings run: | python doc/print_errors.py - - name: Upload HTML documentation without examples artifact + - name: Upload HTML documentation without artifact uses: actions/upload-artifact@v3 with: - name: documentation-no-examples-html + name: documentation-html path: doc/_build/html retention-days: 7 - - name: Build PDF documentation without examples + - name: Build PDF documentation run: | - make -C doc pdf-no-examples - - - name: Upload PDF documentation without examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-no-examples-pdf - path: doc/_build/latex/PyAEDT-Documentation-*.pdf - retention-days: 7 - -# # ================================================================================================= -# # vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv RUNNING ON SELF-HOSTED RUNNER vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv -# # ================================================================================================= - - doc-build-with-examples: - name: Documentation build with examples - if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - runs-on: [ self-hosted, Windows, pyaedt ] - needs: [doc-style] - timeout-minutes: 720 - steps: - - name: Install Git and checkout project - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Create virtual environment - run: | - python -m venv .venv - .venv\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 and documentation dependencies - run: | - .venv\Scripts\Activate.ps1 - pip install .[doc] - - - name: Retrieve PyAEDT version - id: version - run: | - .venv\Scripts\Activate.ps1 - echo "PYAEDT_VERSION=$(python -c 'from ansys.aedt.core import __version__; print(__version__)')" >> $GITHUB_OUTPUT - echo "PyAEDT version is: $(python -c "from ansys.aedt.core import __version__; print(__version__)")" - - - name: Install CI dependencies (e.g. vtk-osmesa) - run: | - .venv\Scripts\Activate.ps1 - # Uninstall conflicting dependencies - pip uninstall --yes vtk - pip install --extra-index-url https://wheels.vtk.org vtk-osmesa - - # TODO: Update this step once pyaedt-examples is ready - # NOTE: Use environment variable to keep the doctree and avoid redundant build for PDF pages - - name: Build HTML documentation with examples - env: - SPHINXBUILD_KEEP_DOCTREEDIR: "1" - run: | - .venv\Scripts\Activate.ps1 - .\doc\make.bat clean - .\doc\make.bat html - - # TODO: Keeping this commented as reminder of https://github.com/ansys/pyaedt/issues/4296 - # # Verify that sphinx generates no warnings - # - name: Check for warnings - # run: | - # .venv\Scripts\Activate.ps1 - # python doc/print_errors.py - - # Use environment variable to remove the doctree after the build of PDF pages - - name: Build PDF documentation with examples - env: - SPHINXBUILD_KEEP_DOCTREEDIR: "0" - run: | - .venv\Scripts\Activate.ps1 - .\doc\make.bat pdf - - # - name: Add assets to HTML docs - # run: | - # zip -r documentation-html.zip ./doc/_build/html - # mv documentation-html.zip ./doc/_build/html/_static/assets/download/ - # cp doc/_build/latex/PyAEDT-Documentation-*.pdf ./doc/_build/html/_static/assets/download/pyaedt.pdf - - - name: Upload HTML documentation with examples artifact - uses: actions/upload-artifact@v3 - with: - name: documentation-html - path: doc/_build/html - retention-days: 7 + make -C doc pdf - - name: Upload PDF documentation without examples artifact + - name: Upload PDF documentation uses: actions/upload-artifact@v3 with: name: documentation-pdf @@ -492,7 +401,7 @@ jobs: release: name: Release project if: github.event_name == 'push' && contains(github.ref, 'refs/tags') - needs: [package, doc-build-with-examples] + needs: [package, doc-build] runs-on: ubuntu-latest steps: - name: Release to the public PyPI repository diff --git a/doc/Makefile b/doc/Makefile index 6b135dfaa78..8fefd56a79d 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -43,39 +43,16 @@ clean: .install-deps # @echo # @echo "Check finished. Report is in $(LINKCHECKDIR)." -html-no-examples: .install-deps - @echo "Building HTML pages without examples." - export PYAEDT_DOC_RUN_EXAMPLES="0" - export PYAEDT_DOC_USE_GIF="1" - @# FIXME: currently linkcheck freezes and further investigation must be performed - @# @$(SPHINXBUILD) -M linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(LINKCHECKOPTS) $(O) - @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)." - html: .install-deps - @echo "Building HTML pages with examples." - export PYAEDT_DOC_RUN_EXAMPLES="1" - export PYAEDT_DOC_USE_GIF="1" + @echo "Building HTML pages." @# FIXME: currently linkcheck freezes and further investigation must be performed @# @$(SPHINXBUILD) -M linkcheck "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(LINKCHECKOPTS) $(O) @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)." -pdf-no-examples: .install-deps - @echo "Building PDF pages without examples." - export PYAEDT_DOC_RUN_EXAMPLES="0" - export PYAEDT_DOC_USE_GIF="0" - @$(SPHINXBUILD) -M latex "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - cd $(BUILDDIR)/latex && latexmk -r latexmkrc -pdf *.tex -interaction=nonstopmode || true - (test -f $(BUILDDIR)/latex/PyAEDT-Documentation-*.pdf && echo pdf exists) || exit 1 - @echo "Build finished. The PDF pages are in $(BUILDDIR)." - pdf: .install-deps - @echo "Building PDF pages with examples." - export PYAEDT_DOC_RUN_EXAMPLES="1" - export PYAEDT_DOC_USE_GIF="0" + @echo "Building PDF pages." @$(SPHINXBUILD) -M latex "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) cd $(BUILDDIR)/latex && latexmk -r latexmkrc -pdf *.tex -interaction=nonstopmode || true (test -f $(BUILDDIR)/latex/PyAEDT-Documentation-*.pdf && echo pdf exists) || exit 1 diff --git a/doc/make.bat b/doc/make.bat index bc9100f4b20..111ff76f89a 100644 --- a/doc/make.bat +++ b/doc/make.bat @@ -27,9 +27,7 @@ REM End of CICD dedicated setup if "%1" == "" goto help if "%1" == "clean" goto clean if "%1" == "html" goto html -if "%1" == "html-no-examples" goto html-no-examples if "%1" == "pdf" goto pdf -if "%1" == "pdf-no-examples" goto pdf-no-examples %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( @@ -59,23 +57,7 @@ for /d /r %SOURCEDIR% %%d in (_autosummary) do @if exist "%%d" rmdir /s /q "%%d" goto end :html -echo Building HTML pages with examples -set PYAEDT_DOC_RUN_EXAMPLES=1 -set PYAEDT_DOC_USE_GIF=1 -::FIXME: currently linkcheck freezes and further investigation must be performed -::%SPHINXBUILD% -M linkcheck %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %LINKCHECKOPTS% %O% -%SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% -echo -echo "Build finished. The HTML pages are in %BUILDDIR%." -goto end - -:html-no-examples -echo Building HTML pages without examples -set PYAEDT_DOC_RUN_EXAMPLES=0 -set PYAEDT_DOC_USE_GIF=1 -if not exist "source\examples" mkdir "source\examples" -echo Examples> source\examples\index.rst -echo ========> source\examples\index.rst +echo Building HTML pages ::FIXME: currently linkcheck freezes and further investigation must be performed ::%SPHINXBUILD% -M linkcheck %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %LINKCHECKOPTS% %O% %SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% @@ -84,25 +66,7 @@ echo "Build finished. The HTML pages are in %BUILDDIR%." goto end :pdf -echo Building PDF pages with examples -set PYAEDT_DOC_RUN_EXAMPLES=1 -set PYAEDT_DOC_USE_GIF=0 -%SPHINXBUILD% -M latex %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -cd "%BUILDDIR%\latex" -for %%f in (*.tex) do ( -xelatex "%%f" --interaction=nonstopmode) -echo "Build finished. The PDF pages are in %BUILDDIR%." -goto end - -:pdf-no-examples -echo Building PDF pages without examples -set PYAEDT_DOC_RUN_EXAMPLES=0 -set PYAEDT_DOC_USE_GIF=0 -if not exist "source\examples" mkdir "source\examples" -echo Examples> source\examples\index.rst -echo ========> source\examples\index.rst -::FIXME: currently linkcheck freezes and further investigation must be performed -::%SPHINXBUILD% -M linkcheck %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %LINKCHECKOPTS% %O% +echo Building PDF pages %SPHINXBUILD% -M latex %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% cd "%BUILDDIR%\latex" for %%f in (*.tex) do ( diff --git a/doc/source/User_guide/index.rst b/doc/source/User_guide/index.rst index 1c1ae73d09a..4fc34833d2b 100644 --- a/doc/source/User_guide/index.rst +++ b/doc/source/User_guide/index.rst @@ -6,7 +6,7 @@ User guide This section provides brief tutorials for helping you understand how to use PyAEDT effectively. -For end-to-end examples, see `Examples `_. +For end-to-end examples, see `Examples `_. .. grid:: 2 diff --git a/doc/source/conf.py b/doc/source/conf.py index 67397d9d91f..ba352a4086c 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -129,9 +129,6 @@ def setup(app): os.environ["PYAEDT_NON_GRAPHICAL"] = "1" os.environ["PYAEDT_DOC_GENERATION"] = "1" -# Do not run examples by default -run_examples = bool(int(os.getenv("PYAEDT_DOC_RUN_EXAMPLES", "0"))) -use_gif = bool(int(os.getenv("PYAEDT_DOC_USE_GIF", "1"))) # -- General configuration --------------------------------------------------- @@ -258,57 +255,6 @@ def setup(app): # gallery build requires AEDT install # if is_windows and bool(os.getenv("PYAEDT_CI_RUN_EXAMPLES", "0")): -if run_examples: - import pyvista - - # PyVista settings - - # Ensure that offscreen rendering is used for docs generation - pyvista.OFF_SCREEN = True - # Save figures in specified directory - pyvista.FIGURE_PATH = os.path.join(os.path.abspath("./images/"), "auto-generated/") - if not os.path.exists(pyvista.FIGURE_PATH): - os.makedirs(pyvista.FIGURE_PATH) - # Necessary for pyvista when building the sphinx gallery - pyvista.BUILDING_GALLERY = True - - # Manage errors - pyvista.set_error_output_file("errors.txt") - # Must be less than or equal to the XVFB window size - pyvista.global_theme["window_size"] = np.array([1024, 768]) - - # suppress annoying matplotlib bug - warnings.filterwarnings( - "ignore", - category=UserWarning, - message="Matplotlib is currently using agg, which is a non-GUI backend, so it cannot show the figure.", - ) - - 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": r"flycheck.*", - "thumbnail_size": (350, 350), - } - if not use_gif: - gif_ignore_pattern = r"|.*Maxwell2D_Transient\.py|.*Maxwell2D_DCConduction\.py|.*Hfss_Icepak_Coupling\.py|.*SBR_Time_Plot\.py" - sphinx_gallery_conf["ignore_pattern"] = sphinx_gallery_conf["ignore_pattern"] + gif_ignore_pattern # -- Options for HTML output ------------------------------------------------- html_short_title = html_title = "PyAEDT" diff --git a/doc/source/index.rst b/doc/source/index.rst index 253bc4889b2..32528e3a1a9 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -46,8 +46,7 @@ enabling straightforward and efficient automation in your workflow. It describes how the methods work and the parameters that can be used. .. grid-item-card:: Examples :fa:`scroll` - :link: examples/index - :link-type: doc + :link: https://examples.aedt.docs.pyansys.com/ Explore examples that show how to use PyAEDT to perform different types of simulations. @@ -59,6 +58,7 @@ enabling straightforward and efficient automation in your workflow. Learn how to contribute to the PyAEDT codebase or documentation. + .. toctree:: :hidden: @@ -66,4 +66,4 @@ enabling straightforward and efficient automation in your workflow. Getting_started/index User_guide/index API/index - examples/index + Examples diff --git a/examples/00-EDB/Readme.txt b/examples/00-EDB/Readme.txt deleted file mode 100644 index 2294f151360..00000000000 --- a/examples/00-EDB/Readme.txt +++ /dev/null @@ -1,20 +0,0 @@ -EDB examples -~~~~~~~~~~~~ -EDB is a powerful API for efficiently controlling PCB data. -You can either use EDB standalone or embedded in HFSS 3D Layout in AEDT. -The ``EDB`` class in now part of the PyEDB package, which is currently installed with PyAEDT and backward-compatible with PyAEDT. -All EDB related examples have been moved -to the `Examples page `_ in the PyEDB -documentation. -These examples use EDB (Electronics Database) with PyAEDT. - -.. code:: python - - # Launch the latest installed version of AEDB. - import ansys.aedt.core - edb = ansys.aedt.core.Edb("mylayout.aedb") - - # You can also launch EDB directly from PyEDB. - - import pyedb - edb = pyedb.Edb("mylayout.aedb") diff --git a/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py b/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py deleted file mode 100644 index 8aac5bd56c3..00000000000 --- a/examples/01-HFSS3DLayout/Dcir_in_3DLayout.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -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. -""" - -import os -import tempfile -import ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Configure EDB for DCIR analysis -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copy example into temporary folder -temp_dir = tempfile.gettempdir() -dst_dir = os.path.join(temp_dir, ansys.aedt.core.generate_unique_name("pyaedt_dcir")) -os.mkdir(dst_dir) -local_path = ansys.aedt.core.downloads.download_aedb(dst_dir) - -##################################################################################### -# Load example board into EDB - -appedb = ansys.aedt.core.Edb(local_path, edbversion=aedt_version) - -##################################################################################### -# Create pin group on VRM positive pins - -gnd_name = "GND" -appedb.siwave.create_pin_group_on_net( - reference_designator="U3A1", - 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( - reference_designator="U3A1", - 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", - magnitude=3.3, - name="U3A1-BST_V3P3_S5" -) - -##################################################################################### -# Create pin group on sink component positive pins - -appedb.siwave.create_pin_group_on_net( - reference_designator="U2A5", - net_name="V3P3_S5", - group_name="U2A5-V3P3_S5") - -##################################################################################### -# Create pin group on sink component negative pins - -appedb.siwave.create_pin_group_on_net( - reference_designator="U2A5", - net_name="GND", - group_name="U2A5-GND") - -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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", - magnitude=1, - 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 = ansys.aedt.core.Desktop(aedt_version, non_graphical=False, new_desktop=True) -hfss3dl = ansys.aedt.core.Hfss3dLayout(local_path) -hfss3dl.analyze() -hfss3dl.save_project() - -############################################################################### -# Get element data -# ~~~~~~~~~~~~~~~~~~~ -# Get current source - -current_source = hfss3dl.get_dcir_element_data_current_source(setup="my_setup") -print(current_source) - -# ~~~~~~~~~~~~~~~~~~~ -# Get via information - -via = hfss3dl.get_dcir_element_data_via(setup="my_setup") -print(via) - - -############################################################################### -# Get voltage -# ~~~~~~~~~~~ -# Get voltage from dcir solution data -voltage = hfss3dl.get_dcir_solution_data(setup="my_setup", show="Sources", category="Voltage") -print({expression: voltage.data_magnitude(expression) for expression in voltage.expressions}) - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -desktop.release_desktop() diff --git a/examples/01-HFSS3DLayout/EDB_in_3DLayout.py b/examples/01-HFSS3DLayout/EDB_in_3DLayout.py deleted file mode 100644 index 7690e708c6b..00000000000 --- a/examples/01-HFSS3DLayout/EDB_in_3DLayout.py +++ /dev/null @@ -1,124 +0,0 @@ -""" -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 ansys.aedt.core - -tmpfold = tempfile.gettempdir() -temp_folder = os.path.join(tmpfold, ansys.aedt.core.generate_unique_name("Example")) -if not os.path.exists(temp_folder): - os.makedirs(temp_folder) -print(temp_folder) - -############################################################################### -# Copy example into temporary folder -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Copy an example into the temporary folder. - -targetfile = ansys.aedt.core.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``. - -non_graphical = False -NewThread = True - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Initialize AEDT and launch HFSS 3D Layout -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize AEDT and launch HFSS 3D Layout. -# The ``h3d`` object contains the :class:`ansys.aedt.core.Edb` class query methods. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, NewThread) -if os.path.exists(aedt_file): - os.remove(aedt_file) -h3d = ansys.aedt.core.Hfss3dLayout(targetfile) -h3d.save_project(os.path.join(temp_folder, "edb_demo.aedt")) - -############################################################################### -# 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:`ansys.aedt.core.modules.layer_stackup.Layer.update_stackup_layer` method -# applies modifications to the layout. - -top = h3d.modeler.layers.layers[h3d.modeler.layers.layer_id("TOP")] -top.is_visible_component = False - -bot = h3d.modeler.layers.layers[h3d.modeler.layers.layer_id("BOTTOM")] -bot.is_visible_component = False - -############################################################################### -# Fit all -# ~~~~~~~ -# Fit all so that you can visualize all. - -h3d.modeler.fit_all() - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.release_desktop` method. -# All methods provide for saving the project before closing. - -h3d.close_project() -d.release_desktop() diff --git a/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py b/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py deleted file mode 100644 index 3be42cefa3c..00000000000 --- a/examples/01-HFSS3DLayout/HFSS3DLayout_Via.py +++ /dev/null @@ -1,127 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. -import ansys.aedt.core -import os - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 = ansys.aedt.core.Hfss3dLayout(version=aedt_version, new_desktop=True, non_graphical=non_graphical) - -############################################################################### -# Set up variables -# ~~~~~~~~~~~~~~~~ -# Set up all parametric variables to use in the layout. - -h3d["viatotrace"] = "5mm" -h3d["viatovia"] = "10mm" -h3d["w1"] = "1mm" -h3d["sp"] = "0.5mm" -h3d["len"] = "50mm" - -############################################################################### -# Add stackup layers -# ~~~~~~~~~~~~~~~~~~ -# Add stackup layers. - -h3d.modeler.layers.add_layer(layer="GND", layer_type="signal", thickness="0", isnegative=True) -h3d.modeler.layers.add_layer(layer="diel", layer_type="dielectric", thickness="0.2mm", material="FR4_epoxy") -h3d.modeler.layers.add_layer(layer="TOP", layer_type="signal", thickness="0.035mm", elevation="0.2mm") - - -############################################################################### -# Create signal net and ground planes -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a signal net and ground planes. - -h3d.modeler.create_line(layer="TOP", - center_line_coordinates=[[0, 0], ["len", 0]], - lw="w1", - name="microstrip", - net="microstrip") -h3d.modeler.create_rectangle(layer="TOP", origin=[0, "-w1/2-sp"], sizes=["len", "-w1/2-sp-20mm"]) -h3d.modeler.create_rectangle(layer="TOP", origin=[0, "w1/2+sp"], sizes=["len", "w1/2+sp+20mm"]) - -############################################################################### -# Create vias -# ~~~~~~~~~~~ -# Create vias with parametric positions. - -h3d.modeler.create_via(x="viatovia", y="-viatotrace", name="via1") -h3d.modeler.create_via(x="viatovia", y="viatotrace", name="via2") -h3d.modeler.create_via(x="2*viatovia", y="-viatotrace") -h3d.modeler.create_via(x="2*viatovia", y="viatotrace") -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() -h3d.create_linear_count_sweep(setup=setup.name, unit="GHz", start_frequency=3, stop_frequency=7, - num_of_freq_points=1001, save_fields=False, sweep_type="Interpolating", - interpolation_tol_percent=1, interpolation_max_solutions=255, 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. - -traces = h3d.get_traces_for_plot(first_element_filter="Port1", category="S") - -solutions = h3d.post.get_solution_data(expressions=traces) -solutions.plot(formula="db20") - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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 deleted file mode 100644 index 2d18d039838..00000000000 --- a/examples/01-HFSS3DLayout/Hfss3DComponent.py +++ /dev/null @@ -1,245 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 -trace_length = 30 -diel_height = "121mil" -sig_height = "5mil" -max_steps = 3 -freq = "3GHz" -new_session = True - -############################################################################### -# 3D Component Definition -# ~~~~~~~~~~~~~~~~~~~~~~~ -# File to be used in the example - -component3d = ansys.aedt.core.downloads.download_file("component_3d", "SMA_RF_Jack.a3dcomp",) - -############################################################################### -# 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 = ansys.aedt.core.Hfss(new_desktop=True, version=aedt_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 -# ~~~~~~~~~~~~~~~~~ -# Pyaedt has a Stackup class which allows to parametrize stacked structures. - -stackup = hfss.add_stackup_3d() -s1 = stackup.add_signal_layer("L1", thickness=sig_height) -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" -stackup.dielectric_width = "20mm" -stackup.dielectric_length = "40mm" -stackup.dielectric_y_position = "-dielectric_width/2" -stackup.dielectric_x_position = "-dielectric_length/4" - -############################################################################### -# 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. - -p1 = stackup.add_padstack("gnd_via", material="cloned_copper") -p1.set_start_layer("L1") -p1.set_stop_layer("G1") -p1.set_all_antipad_value(1.3) -p1.set_all_pad_value(0) -p1.num_sides = 8 -p1.add_via(-3.2, -3.2) -p1.add_via(-3.2, 3.2) -p1.add_via(3.2, -3.2) -p1.add_via(3.2, 3.2) -p2 = stackup.add_padstack("signal_via", material="cloned_copper") - -p2.set_start_layer("L1") -p2.set_stop_layer("G1") -p2.set_all_antipad_value(0.7) -p2.set_all_pad_value(0) -p2.padstacks_by_layer["L1"].pad_radius = 0.3048 -p2.add_via(0, 0) - -############################################################################### -# Trace Definition -# ~~~~~~~~~~~~~~~~ -# The trace will connect the pin to the port on layer L1. - -t1 = s1.add_trace(trace_width, trace_length) -rect1 = hfss.modeler.create_rectangle(orientation=hfss.PLANE.YZ, - origin=["0.75*dielectric_length", "-5*" + t1.width.name, "0mm"], - sizes=["15*" + t1.width.name, "-3*" + stackup.thickness.name]) -p1 = hfss.wave_port(assignment=rect1, reference="G1", name="P1") - -############################################################################### -# Set Simulation Boundaries -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define regione and simulation boundaries. - -hfss.change_material_override(True) -region = hfss.modeler.create_region([0, 0, 0, 0, 0, 100]) -sheets = [i for i in region.faces] -hfss.assign_radiation_boundary_to_faces(sheets) - -############################################################################### -# Create Setup -# ~~~~~~~~~~~~ -# Iterations will be reduced to reduce simulation time. - -setup1 = hfss.create_setup() -sweep1 = hfss.create_linear_count_sweep(setup1.name, "GHz", 0.01, 8, 1601, sweep_type="Interpolating") -setup1.props["Frequency"] = freq -setup1.props["MaximumPasses"] = max_steps - -############################################################################### -# Solve Setup -# ~~~~~~~~~~~ -# Save the project first and then solve the setup. - -hfss.save_project() -hfss.analyze() - -############################################################################### -# 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, formula="db20") - -############################################################################### -# 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 application - -h3d = ansys.aedt.core.Hfss3dLayout() - -############################################################################### -# 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 a 3d component by specifying the .a3dcomp file path. - -comp = h3d.modeler.place_3d_component( - component_path=component3d, number_of_terminals=1, placement_layer="G1", component_name="my_connector", - pos_x=0.000, pos_y=0.000 -) - -############################################################################### -# Create signal net and ground planes -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a signal net and ground planes. - -h3d["len"] = str(trace_length) + "mm" -h3d["w1"] = str(trace_width) + "mm" - -line = h3d.modeler.create_line("L1", [[0, 0], ["len", 0]], lw="w1", name="microstrip", net="microstrip") -h3d.create_edge_port(line, h3d.modeler[line.name].top_edge_x, is_wave_port=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 -# ~~~~~~~~~~~~ -# Iterations will be reduced to reduce simulation time. - -h3d.set_meshing_settings(mesh_method="PhiPlus", enable_intersections_check=False) -h3d.edit_hfss_extents(diel_extent_horizontal_padding="0.2", air_vertical_positive_padding="0", - air_vertical_negative_padding="2", airbox_values_as_dim=False) -setup1 = h3d.create_setup() -sweep1 = h3d.create_linear_count_sweep(setup1.name, - "GHz", - 0.01, - 8, - 1601, - sweep_type="Interpolating") -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) -solutions.plot(traces, formula="db20") - -h3d.save_project() -h3d.release_desktop() diff --git a/examples/01-HFSS3DLayout/Readme.txt b/examples/01-HFSS3DLayout/Readme.txt deleted file mode 100644 index daf9b1637e8..00000000000 --- a/examples/01-HFSS3DLayout/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -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. diff --git a/examples/01-Modeling-Setup/Configurations.py b/examples/01-Modeling-Setup/Configurations.py deleted file mode 100644 index 5f720144699..00000000000 --- a/examples/01-Modeling-Setup/Configurations.py +++ /dev/null @@ -1,135 +0,0 @@ -""" -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 ansys.aedt.core. - -import os -import ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Open project -# ~~~~~~~~~~~~ -# Download the project, open it, and save it to the temporary folder. - -project_full_name = ansys.aedt.core.downloads.download_icepak(ansys.aedt.core.generate_unique_folder_name(folder_name="Graphic_Card")) - -ipk = ansys.aedt.core.Icepak(project=project_full_name, version=aedt_version, - new_desktop=True, non_graphical=non_graphical) -ipk.autosave_disable() - -############################################################################### -# 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 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 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. - -setup1 = ipk.create_setup() -setup1["FlowRegime"] = "Turbulent" -setup1["Max Iterations"] = 5 -setup1["Solver Type Pressure"] = "flex" -setup1["Solver Type Temperature"] = "flex" -ipk.save_project(r"C:\temp\Graphic_card.aedt") - -############################################################################### -# Export project to step file -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Export the current project to the step file. - -filename = ipk.design_name -file_path = os.path.join(ipk.working_directory, filename + ".step") -ipk.export_3d_model(file_name=filename, file_path=ipk.working_directory, file_format=".step", assignment_to_export=[], - assignment_to_remove=[]) - -############################################################################### -# 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 an Icepak project and import the step. - -app = ansys.aedt.core.Icepak(project="new_proj_Ipk") -app.modeler.import_3d_cad(file_path) - -############################################################################### -# 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 the project. - -app.release_desktop() diff --git a/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py b/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py deleted file mode 100644 index ff28f7ae91c..00000000000 --- a/examples/01-Modeling-Setup/HFSS_CoordinateSystem.py +++ /dev/null @@ -1,281 +0,0 @@ -""" -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 - -import os - -import ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode. - -d = ansys.aedt.core.launch_desktop(version=aedt_version, non_graphical=non_graphical, new_desktop=True) - -############################################################################### -# Insert HFSS design -# ~~~~~~~~~~~~~~~~~~ -# Insert an HFSS design with the default name. - -hfss = ansys.aedt.core.Hfss(project=ansys.aedt.core.generate_unique_project_name(folder_name="CoordSysDemo")) - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# The ``cs1`` object exposes properties and methods to manipulate the -# coordinate system. The origin can be changed. - -cs1["OriginX"] = 10 -cs1.props["OriginY"] = 10 -cs1.props["OriginZ"] = 10 - -# Pointing vectors can be changed - -ypoint = [0, -1, 0] -cs1.props["YAxisXvec"] = ypoint[0] -cs1.props["YAxisYvec"] = ypoint[1] -cs1.props["YAxisZvec"] = ypoint[2] - -############################################################################### -# Rename coordinate system -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Rename the coordinate system. - -cs1.rename("newCS") - -############################################################################### -# 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. - -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 the coordinate system. - -cs1.delete() - -############################################################################### -# Create coordinate system by defining axes -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a coordinate system by defining the axes. During creation, you can -# specify all coordinate system properties. - -cs2 = hfss.modeler.create_coordinate_system( - 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 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 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 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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 -# specify starting and ending points for the axis. - -box = hfss.modeler.create_box([0, 0, 0], [2, 2, 2]) -face = box.faces[0] -fcs1 = hfss.modeler.create_face_coordinate_system( - face=face, origin=face.edges[0], axis_position=face.edges[1], name="FCS1" -) - -############################################################################### -# 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. - -fcs2 = hfss.modeler.create_face_coordinate_system( - face=face, origin=face, axis_position=face.edges[0].vertices[0], name="FCS2" -) - -############################################################################### -# 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. - -fcs3 = hfss.modeler.create_face_coordinate_system(face=face, origin=face, axis_position=face.edges[0], axis="Y") - -# Axis can also be changed after coordinate system creation -fcs3.props["WhichAxis"] = "X" - -############################################################################### -# 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. - -fcs4 = hfss.modeler.create_face_coordinate_system(face=face, origin=face, axis_position=face.edges[1], rotation=10.3) - -# 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 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. - -fcs5 = hfss.modeler.create_face_coordinate_system( - face=face, origin=face, axis_position=face.edges[2], offset=[0.5, 0.3] -) - -# The offset can also be changed after the coordinate system is created. -fcs5.props["XOffset"] = "0.2mm" -fcs5.props["YOffset"] = "0.1mm" - -############################################################################### -# 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. - -face = box.faces[1] -fcs6 = hfss.modeler.create_face_coordinate_system(face=face, origin=face, axis_position=face.edges[0]) -cs_fcs = hfss.modeler.create_coordinate_system( - name="CS_FCS", origin=[0, 0, 0], reference_cs=fcs6.name, mode="view", view="iso" -) - -############################################################################### -# Create object coordinate system -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create object coordinate system with origin on face - -obj_cs = hfss.modeler.create_object_coordinate_system(assignment=box, origin=box.faces[0], x_axis=box.edges[0], - y_axis=[0, 0, 0], name="box_obj_cs") -obj_cs.rename("new_obj_cs") - -############################################################################### -# Create object coordinate system -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create object coordinate system with origin on edge - -obj_cs_1 = hfss.modeler.create_object_coordinate_system(assignment=box.name, origin=box.edges[0], x_axis=[1, 0, 0], - y_axis=[0, 1, 0], name="obj_cs_1") -obj_cs_1.set_as_working_cs() - -############################################################################### -# Create object coordinate system -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create object coordinate system with origin specified on point - -obj_cs_2 = hfss.modeler.create_object_coordinate_system(assignment=box.name, origin=[0, 0.8, 0], x_axis=[1, 0, 0], - y_axis=[0, 1, 0], name="obj_cs_2") -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 with origin on vertex - -obj_cs_3 = hfss.modeler.create_object_coordinate_system(assignment=box.name, origin=box.vertices[1], - x_axis=box.faces[2], y_axis=box.faces[4], name="obj_cs_3") -obj_cs_3.props["MoveToEnd"] = False -obj_cs_3.update() - -############################################################################### -# 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 an existing coordinate system. - -css = hfss.modeler.coordinate_systems -cs_selected = css[0] -cs_selected.delete() - -############################################################################### -# 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. - -hfss.modeler.create_box([-10, -10, -10], [20, 20, 20], "Box1") -p = hfss.modeler["Box1"].faces[0].vertices[0].position -print("Global: ", p) -p2 = hfss.modeler.global_to_cs(p, "CS5") -print("CS5 :", p2) - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulaton completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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 deleted file mode 100644 index c6b2247aafe..00000000000 --- a/examples/01-Modeling-Setup/Optimetrics.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -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 ansys.aedt.core - -import os - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the ``Hfss`` object and create two needed design variables, -# ``w1`` and ``w2``. - -hfss = ansys.aedt.core.Hfss(version=aedt_version, new_desktop=True, non_graphical=non_graphical, solution_type="Modal") -hfss["w1"] = "1mm" -hfss["w2"] = "100mm" - -############################################################################### -# 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, - "WG17", - wg_thickness="w1", - wg_length="w2", - create_sheets_on_openings=True, -) - -model = hfss.plot(show=False) - -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 a setup and a frequency sweep to use as the base for optimetrics -# setups. - -setup = hfss.create_setup() -hfss.create_linear_step_sweep( - setup=setup.name, - unit="GHz", - start_frequency=1, - stop_frequency=5, - step_size=0.1, - name="Sweep1", - save_fields=True -) - -############################################################################### -# Optimetrics analysis -# ---------------------- -# Create parametrics analysis -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a simple optimetrics parametrics analysis with output calculations. - -sweep = hfss.parametrics.add("w2", 90, 200, 5) -sweep.add_variation("w1", 0.1, 2, 10) -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"}, optimization_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"}) -sweep3.add_variation("w1", 0.1, 3, 0.5) -sweep3.add_goal(calculation="dB(S(1,1))", ranges={"Freq": "2.6GHz"}) -sweep3.add_goal(calculation="dB(S(1,1))", ranges={"Freq": ("2.6GHz", "5GHz")}) -sweep3.add_goal( - calculation="dB(S(1,1))", - ranges={"Freq": ("2.6GHz", "5GHz")}, - 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"}, optimization_type="DesignExplorer") -sweep4.add_goal(calculation="dB(S(1,1))", ranges={"Freq": "2.6GHz"}) - -############################################################################### -# 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"}, optimization_type="DXDOE") - -############################################################################### -# Create DOE based on a goal and calculation -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a DOE based on a goal and a calculation. - -region = hfss.modeler.create_region() -hfss.assign_radiation_boundary_to_objects(region) -hfss.insert_infinite_sphere(name="Infinite_1") -sweep6 = hfss.optimizations.add(calculation="RealizedGainTotal", - ranges={"Freq": "5GHz", "Theta": ["0deg", "10deg", "20deg"], "Phi": "0deg"}, - solution=hfss.nominal_adaptive, context="Infinite_1") - -############################################################################### -# Close AEDT -# ---------- -# After the simulaton completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.release_desktop` method. -# All methods provide for saving the project before closing. - -hfss.release_desktop() diff --git a/examples/01-Modeling-Setup/Polyline_Primitives.py b/examples/01-Modeling-Setup/Polyline_Primitives.py deleted file mode 100644 index 4ea86d8e708..00000000000 --- a/examples/01-Modeling-Setup/Polyline_Primitives.py +++ /dev/null @@ -1,295 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 a :class:`ansys.aedt.core.maxwell.Maxwell3d` object and set the unit type to ``"mm"``. - -M3D = ansys.aedt.core.Maxwell3d(solution_type="Transient", design="test_polyline_3D", version=aedt_version, - new_desktop=True, non_graphical=non_graphical, ) -M3D.modeler.model_units = "mm" -prim3D = M3D.modeler - -############################################################################### -# Define variables -# ~~~~~~~~~~~~~~~~ -# Define two design variables as parameters for the polyline objects. - -M3D["p1"] = "100mm" -M3D["p2"] = "71mm" - -############################################################################### -# 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 -# ------------------- -# The following examples are for creating polyline primitives. - -# 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), -# ``AngularArc`` (center-point + angle), and ``Spline``. - -P = prim3D.create_polyline(points=test_points[0:2], name="PL01_line") - -print("Created Polyline with name: {}".format(prim3D.objects[P.id].name)) -print("Segment types : {}".format([s.type for s in P.segment_types])) -print("primitive id = {}".format(P.id)) - -############################################################################### -# 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. - -P = prim3D.create_polyline(points=test_points[0:3], segment_type="Arc", name="PL02_arc") - -print("Created object with id {} and name {}.".format(P.id, prim3D.objects[P.id].name)) - -############################################################################### -# 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`` -# must contain at least four position values. - -P = prim3D.create_polyline(points=test_points, segment_type=prim3D.polyline_segment("Spline", num_points=4), - name="PL03_spline_4pt") - -############################################################################### -# 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 -# plane of the active coordinate system. The starting point and the center point -# must therefore have one coordinate value (X, Y, or Z) with the same value. -# -# Here ``start-point`` and ``center-point`` have a common Z coordinate, ``"0mm"``. -# The curve is therefore rotated in the XY plane with Z = ``"0mm"``. - -start_point = [100, 100, 0] -center_point = [0, 0, 0] -P = prim3D.create_polyline(points=[start_point], - segment_type=prim3D.polyline_segment("AngularArc", arc_center=center_point, - arc_angle="30deg"), 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 -# the plane explicitly. - -start_point = [100, 0, 0] -center_point = [0, 0, 0] -P = prim3D.create_polyline(points=[start_point], - segment_type=prim3D.polyline_segment("AngularArc", arc_center=center_point, - arc_angle="30deg", arc_plane="XY"), - name="PL04_center_point_arc_rot_XY") -P = prim3D.create_polyline(points=[start_point], - segment_type=prim3D.polyline_segment("AngularArc", arc_center=center_point, - arc_angle="30deg", arc_plane="ZX"), - name="PL04_center_point_arc_rot_ZX") - -############################################################################### -# Compound polylines -# ------------------ -# You can use a list of points in a single command to create a multi-segment -# polyline. -# -# By default, if no specification of the type of segments is given, all points -# are connected by line segments. - -P = prim3D.create_polyline(points=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(points=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(points=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(points=test_points, cover_surface=True, name="SPL01_segmented_compound_line") - -############################################################################### -# Compound lines -# -------------- -# The following examples are for inserting compound lines. -# -# 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 -# original polyline object, it is determined automatically that the segment is -# inserted after the first segment of the original polyline. - -P = prim3D.create_polyline(points=test_points, close_surface=True, name="PL08_segmented_compound_insert_segment") - -p2 = P.points[1] -insert_point = ["-100mm", "20mm", "0mm"] - -P.insert_segment(points=[insert_point, p2]) - -############################################################################### -# 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 -# that the segment is inserted after the first segment of the original polyline. - -P = prim3D.create_polyline(points=test_points, close_surface=False, name="PL08_segmented_compound_insert_arc") - -start_point = P.vertex_positions[1] -insert_point1 = ["90mm", "20mm", "0mm"] -insert_point2 = [40, 40, 0] - -P.insert_segment(points=[start_point, insert_point1, insert_point2], segment="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. -# -# Step 1: Draw a center-point arc. - -start_point = [2200.0, 0.0, 1200.0] -arc_center_1 = [1400, 0, 800] -arc_angle_1 = "43.47deg" - -P = prim3D.create_polyline(points=[start_point], - segment_type=prim3D.polyline_segment(type="AngularArc", arc_angle=arc_angle_1, - arc_center=arc_center_1), name="First_Arc") - -############################################################################### -# Step 2: Insert a line segment at the end of the arc with a specified end point. - -start_of_line_segment = P.end_point -end_of_line_segment = [3600, 200, 30] - -P.insert_segment(points=[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" -arc_center_2 = [3400, 200, 3800] - -P.insert_segment(points=[end_of_line_segment], - 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. - -prim3D.create_polyline(points=[start_point, end_of_line_segment], segment_type=[ - prim3D.polyline_segment(type="AngularArc", arc_angle="43.47deg", arc_center=arc_center_1), - prim3D.polyline_segment(type="Line"), - prim3D.polyline_segment(type="AngularArc", arc_angle=arc_angle_2, arc_center=arc_center_2), -], 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. -# Note that the last point of the second arc segment is not defined in -# the position list. - -P = prim3D.create_polyline( - points=[[34.1004, 14.1248, 0], [27.646, 16.7984, 0], [24.9725, 10.3439, 0], [31.4269, 7.6704, 0]], - segment_type=["Arc", "Arc"], cover_surface=True, close_surface=True, name="Rotor_Subtract_25_0", material="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 -# is ``False``, which can be caught at the app level. While this example might -# not be so useful in a Jupyter Notebook, it is important for unit tests. - -MDL_points = [ - ["67.1332mm", "2.9901mm", "0mm"], - ["65.9357mm", "2.9116mm", "0mm"], - ["65.9839mm", "1.4562mm", "0mm"], - ["66mm", "0mm", "0mm"], - ["99mm", "0mm", "0mm"], - ["98.788mm", "6.4749mm", "0mm"], - ["98.153mm", "12.9221mm", "0mm"], - ["97.0977mm", "19.3139mm", "0mm"], -] - - -MDL_segments = ["Line", "Arc", "Line", "Arc", "Line"] -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. - -MDL_segments = ["Line", "Arc", "Line", "Arc"] - -P = prim3D.create_polyline(MDL_points, segment_type=MDL_segments, name="MDL_Polyline") - -############################################################################### -# Save project -# ------------ -# Save the project. - -project_dir = r"C:\temp" -project_name = "Polylines" -project_file = os.path.join(project_dir, project_name + ".aedt") - -M3D.save_project(project_file) - -M3D.release_desktop() diff --git a/examples/01-Modeling-Setup/Readme.txt b/examples/01-Modeling-Setup/Readme.txt deleted file mode 100644 index d9417436357..00000000000 --- a/examples/01-Modeling-Setup/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -General model and setup examples -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -These examples use PyAEDT to show some general model and simulation -setup features inside AEDT. 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 6b9fc242e14..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 ansys.aedt.core -from ansys.aedt.core.generic.general_methods import remove_project_lock - -project_name = ansys.aedt.core.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 = ansys.aedt.core.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 = ansys.aedt.core.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 deleted file mode 100644 index 268fc00f254..00000000000 --- a/examples/02-HFSS/Array.py +++ /dev/null @@ -1,151 +0,0 @@ -""" -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 ansys.aedt.core -from ansys.aedt.core.visualization.advanced.farfield_visualization import FfdSolutionData - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################## -# 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 the 3D component that is needed to run the example. -example_path = ansys.aedt.core.downloads.download_3dcomponent() - -########################################################## -# Launch HFSS and save project -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch HFSS and save the project. -project_name = ansys.aedt.core.generate_unique_project_name(project_name="array") -hfss = ansys.aedt.core.Hfss(project=project_name, - version=aedt_version, - design="Array_Simple", - non_graphical=non_graphical, - new_desktop=True) - -print("Project name " + project_name) - -########################################################## -# 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. -# -# If a 3D component is not available in the design, it is loaded -# into the dictionary from the path that you specify. The following -# code edits the dictionary to point to the location of the A3DCOMP file. - -dict_in = ansys.aedt.core.general_methods.read_json(os.path.join(example_path, "array_simple.json")) -dict_in["Circ_Patch_5GHz1"] = os.path.join(example_path, "Circ_Patch_5GHz.a3dcomp") -dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} -array = hfss.add_3d_component_array_from_json(dict_in) - -########################################################## -# Modify cells -# ~~~~~~~~~~~~ -# Rotate corner elements. - -array.cells[0][0].rotation = 90 -array.cells[0][2].rotation = 90 -array.cells[2][0].rotation = 90 -array.cells[2][2].rotation = 90 - -########################################################## -# Set up simulation -# ~~~~~~~~~~~~~~~~~ -# Set up a simulation and analyze it. - -setup = hfss.create_setup() -setup.props["Frequency"] = "5GHz" -setup.props["MaximumPasses"] = 3 - -hfss.analyze(cores=4) -hfss.save_project() - -########################################################## -# 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_data(setup=hfss.nominal_adaptive, sphere="Infinite Sphere1") - -########################################################## -# Generate contour plot -# ~~~~~~~~~~~~~~~~~~~~~ -# Generate a contour plot. You can define the Theta scan -# and Phi scan. - -ffdata.farfield_data.plot_contour(quantity='RealizedGain', - title='Contour at {}Hz'.format(ffdata.farfield_data.frequency)) - -########################################################## -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT. -# Far field post-processing can be performed without AEDT because the data is stored. - -eep_file = ffdata.metadata_file -working_directory = hfss.working_directory - -hfss.release_desktop() - -########################################################## -# Load far field data -# ~~~~~~~~~~~~~~~~~~~ -# Load far field data stored. - -ffdata = FfdSolutionData(input_file=eep_file) - -########################################################## -# Generate contour plot -# ~~~~~~~~~~~~~~~~~~~~~ -# Generate a contour plot. You can define the Theta scan -# and Phi scan. - -ffdata.plot_contour(quantity='RealizedGain', title='Contour at {}Hz'.format(ffdata.frequency)) - -########################################################## -# Generate 2D cutout plots -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Generate 2D cutout plots. You can define the Theta scan -# and Phi scan. - -ffdata.plot_cut(quantity='RealizedGain', primary_sweep='theta', secondary_sweep_value=[-180, -75, 75], - title='Azimuth at {}Hz'.format(ffdata.frequency), quantity_format="dB10") - -ffdata.plot_cut(quantity='RealizedGain', primary_sweep="phi", secondary_sweep_value=30, title='Elevation', - quantity_format="dB10") - -########################################################## -# Generate 3D plots -# ~~~~~~~~~~~~~~~~~ -# Generate 3D plots. You can define the Theta scan and Phi scan. - -# ffdata.plot_3d(quantity='RealizedGain', -# output_file=os.path.join(working_directory, "Image.jpg"), -# show=False) diff --git a/examples/02-HFSS/Create_3d_Component_and_use_it.py b/examples/02-HFSS/Create_3d_Component_and_use_it.py deleted file mode 100644 index eac8084ebf8..00000000000 --- a/examples/02-HFSS/Create_3d_Component_and_use_it.py +++ /dev/null @@ -1,174 +0,0 @@ -""" -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 ansys.aedt.core import Hfss -from ansys.aedt.core.generic.general_methods import generate_unique_name - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################## -# Launch HFSS -# ~~~~~~~~~~~ -# 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(version=aedt_version, new_desktop=True, close_on_exit=True) - -########################################################## -# Variables -# ~~~~~~~~~ -# PyAEDT can create and store all variables available in AEDT (Design, Project, Post Processing) - -hfss["thick"] = "0.1mm" -hfss["width"] = "1mm" - -########################################################## -# 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"], name="sub", - material="FR4_epoxy") - -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", name="via_inner", - material="copper") - -via_outer = hfss.modeler.create_cylinder(2, ["-width/8", "-width/4", "-thick"], "0.025mm", "thick", name="via_teflon", - material="Teflon_based") - -########################################################## -# 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. - -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 -# ~~~~~~~~~~~~~~~~ -# 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 -# ~~~~~~~~~~~~~~~~~~~ -# 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. - -component_path = os.path.join(tempfile.gettempdir(), generate_unique_name("component_test") + ".aedbcomp") -hfss.modeler.create_3dcomponent(component_path, "patch_antenna") - -########################################################## -# Multiple project management -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# PyAEDT allows to control multiple projects, design and solution type at the same time. - -hfss2 = Hfss(project="new_project", design="new_design") - -########################################################## -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~ -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~ -# 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, coordinate_system="Second_antenna") - -########################################################## -# 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 -# ~~~~~~~~~~ -# 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 - -hfss2.modeler.create_air_region(30, 30, 30, 30, 30, 30) -hfss2.assign_radiation_boundary_to_faces(hfss2.modeler["Region"].faces) - -# Create Setup and Optimetrics -# Once project is ready to be solved, a setup and parametrics analysis can be created with PyAEDT. -# 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 the project. - -hfss2.modeler.fit_all() -hfss2.plot(show=False, output_file=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=True) - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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")) -hfss2.release_desktop() diff --git a/examples/02-HFSS/Flex_CPWG.py b/examples/02-HFSS/Flex_CPWG.py deleted file mode 100644 index c9d3cfb8ac1..00000000000 --- a/examples/02-HFSS/Flex_CPWG.py +++ /dev/null @@ -1,208 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode. - -hfss = ansys.aedt.core.Hfss(version=aedt_version, - solution_type="DrivenTerminal", - new_desktop=True, - non_graphical=non_graphical) -hfss.change_material_override(True) -hfss.change_automatically_use_causal_materials(True) -hfss.create_open_region("100GHz") -hfss.modeler.model_units = "mil" -hfss.mesh.assign_initial_mesh_from_slider(applycurvilinear=True) - -############################################################################### -# Create variables -# ~~~~~~~~~~~~~~~~ -# Create input variables for creating the flex cable CPWG. - -total_length = 300 -theta = 120 -r = 100 -width = 3 -height = 0.1 -spacing = 1.53 -gnd_width = 10 -gnd_thickness = 2 - -xt = (total_length - r * radians(theta)) / 2 - - -############################################################################### -# 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)] - - for i in [radians(i) for i in range(theta)] + [radians(theta + 0.000000001)]: - position_list.append((radius * sin(i), 0, -radius * cos(i))) - - x1, y1, z1 = position_list[-1] - x0, y0, z0 = position_list[-2] - - scale = (xt + extension) / sqrt((x1 - x0) ** 2 + (z1 - z0) ** 2) - x, y, z = (x1 - x0) * scale + x0, 0, (z1 - z0) * scale + z0 - - position_list[-1] = (x, y, z) - return position_list - - -############################################################################### -# Draw signal line -# ~~~~~~~~~~~~~~~~ -# Draw a signal line to create a bent signal wire. - -position_list = create_bending(r, 1) -line = hfss.modeler.create_polyline(points=position_list, material="copper", xsection_type="Rectangle", - xsection_width=height, xsection_height=width) - -############################################################################### -# 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] - -gnd_objs = [] -for gnd in [gnd_r, gnd_l]: - x = hfss.modeler.create_polyline(points=gnd, material="copper", xsection_type="Rectangle", xsection_width=height, - xsection_height=gnd_width) - x.color = (255, 0, 0) - gnd_objs.append(x) - -############################################################################### -# Draw dielectric -# ~~~~~~~~~~~~~~~ -# Draw a dielectric to create a dielectric cable. - -position_list = create_bending(r + (height + gnd_thickness) / 2) - -fr4 = hfss.modeler.create_polyline(points=position_list, material="FR4_epoxy", xsection_type="Rectangle", - xsection_width=gnd_thickness, xsection_height=width + 2 * spacing + 2 * gnd_width) - -############################################################################### -# Create bottom metals -# ~~~~~~~~~~~~~~~~~~~~ -# Create the bottom metals. - -position_list = create_bending(r + height + gnd_thickness, 1) - -bot = hfss.modeler.create_polyline(points=position_list, material="copper", xsection_type="Rectangle", - xsection_width=height, xsection_height=width + 2 * spacing + 2 * gnd_width) - -############################################################################### -# 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 - positions = [i.position for i in face.vertices] - - port_sheet_list = [((x - xc) * 10 + xc, (y - yc) + yc, (z - zc) * 10 + zc) for x, y, z in positions] - s = hfss.modeler.create_polyline(port_sheet_list, cover_surface=True, close_surface=True) - center = [round(i, 6) for i in s.faces[0].center] - - port_block = hfss.modeler.thicken_sheet(s.name, -5) - port_block.name = blockname - for f in port_block.faces: - - if [round(i, 6) for i in f.center] == center: - port_faces.append(f) - - port_block.material_name = "PEC" - - for i in [line, bot] + gnd_objs: - i.subtract([port_block], True) - - print(port_faces) - -############################################################################### -# Create boundary condition -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Creates a Perfect E boundary condition. - -boundary = [] -for face in [fr4.top_face_y, fr4.bottom_face_y]: - s = hfss.modeler.create_object_from_face(face) - boundary.append(s) - hfss.assign_perfecte_to_sheets(s) - -############################################################################### -# 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, reference=reference, name=port_name) - -############################################################################### -# Create setup and sweep -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create the setup and sweep. - -setup = hfss.create_setup("setup1") -setup["Frequency"] = "2GHz" -setup.props["MaximumPasses"] = 10 -setup.props["MinimumConvergedPasses"] = 2 -hfss.create_linear_count_sweep(setup="setup1", units="GHz", start_frequency=1e-1, stop_frequency=4, - num_of_freq_points=101, name="sweep1", save_fields=False, sweep_type="Interpolating") - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -my_plot = hfss.plot(show=False, plot_air_objects=False) -my_plot.show_axes = False -my_plot.show_grid = False -my_plot.plot( - os.path.join(hfss.working_directory, "Image.jpg"), -) - -############################################################################### -# Analyze and release -# ~~~~~~~~~~~~~~~~~~~~ -# Uncomment the ``hfss.analyze`` command if you want to analyze the -# model and release AEDT. - -hfss.release_desktop() diff --git a/examples/02-HFSS/HFSS_Choke.py b/examples/02-HFSS/HFSS_Choke.py deleted file mode 100644 index cb8a66a1fa4..00000000000 --- a/examples/02-HFSS/HFSS_Choke.py +++ /dev/null @@ -1,228 +0,0 @@ -""" -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 ansys.aedt.core -import tempfile - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -project_name = ansys.aedt.core.generate_unique_project_name(root_name=temp_dir.name, folder_name="choke", - project_name="choke") - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Launch HFSS -# ~~~~~~~~~~~ -# Launches HFSS 2023 R2 in graphical mode. - -hfss = ansys.aedt.core.Hfss(project=project_name, - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True, - solution_type="Terminal") - -############################################################################### -# 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 -# ``"Number of Windings"``, ``"Layer"``, and ``"Layer Type"``, that have -# 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 -# one value per dictionary can be ``True``. If all values are ``True``, only the first one -# remains set to ``True``. If all values are ``False``, the first value is chosen as the -# correct one by default. For the dictionaries from ``"Core"`` through ``"Inner Winding"``, -# values must be strings, floats, or integers. -# -# Descriptions follow for primary keys: -# -# - ``"Number of Windings"``: Number of windings around the core -# - ``"Layer"``: Number of layers of all windings -# - ``"Layer Type"``: Whether layers of a winding are linked to each other -# - ``"Similar Layer"``: Whether layers of a winding have the same number of turns and same spacing between turns -# - ``"Mode"``: When there are only two windows, whether they are in common or differential mode -# - ``"Wire Section"``: Type of wire section and number of segments -# - ``"Core"``: Design of the core -# - ``"Outer Winding"``: Design of the first layer or outer layer of a winding and the common parameters for all layers -# - ``"Mid Winding"``: Turns and turns spacing ("Coil Pit") for the second or mid layer if it is necessary -# - ``"Inner Winding"``: Turns and turns spacing ("Coil Pit") for the third or inner layer if it is necessary -# - ``"Occupation(%)"``: An informative parameter that is useless to modify -# -# The following parameter values work. You can modify them if you want. - -values = { - "Number of Windings": {"1": False, "2": True, "3": False, "4": False}, - "Layer": {"Simple": False, "Double": True, "Triple": False}, - "Layer Type": {"Separate": False, "Linked": True}, - "Similar Layer": {"Similar": False, "Different": True}, - "Mode": {"Differential": False, "Common": True}, - "Wire Section": {"None": False, "Hexagon": True, "Octagon": False, "Circle": False}, - "Core": { - "Name": "Core", - "Material": "ferrite", - "Inner Radius": 20, - "Outer Radius": 30, - "Height": 10, - "Chamfer": 0.8, - }, - "Outer Winding": { - "Name": "Winding", - "Material": "copper", - "Inner Radius": 20, - "Outer Radius": 30, - "Height": 10, - "Wire Diameter": 1.5, - "Turns": 20, - "Coil Pit(deg)": 0.1, - "Occupation(%)": 0, - }, - "Mid Winding": {"Turns": 25, "Coil Pit(deg)": 0.1, "Occupation(%)": 0}, - "Inner Winding": {"Turns": 4, "Coil Pit(deg)": 0.1, "Occupation(%)": 0}, -} - -############################################################################### -# 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 the JSON file. The ``check_choke_values`` method takes -# the JSON file path as an argument and does the following: -# -# - Checks if the JSON file is correctly written (as explained in the rules) -# - Checks in equations on windings parameters to avoid having unintended intersections - -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 -# argument. - -list_object = hfss.modeler.create_choke(json_path) -print(list_object) -core = list_object[1] -first_winding_list = list_object[2] -second_winding_list = list_object[3] - -############################################################################### -# Create ground -# ~~~~~~~~~~~~~ -# Create a ground. - -ground_radius = 1.2 * dictionary_values[1]["Outer Winding"]["Outer Radius"] -ground_position = [0, 0, first_winding_list[1][0][2] - 2] -ground = hfss.modeler.create_circle("XY", ground_position, ground_radius, name="GND", material="copper") -coat = hfss.assign_coating(ground, is_infinite_ground=True) - -############################################################################### -# Create lumped ports -# ~~~~~~~~~~~~~~~~~~~ -# Create lumped ports. - -port_position_list = [ - [first_winding_list[1][0][0], first_winding_list[1][0][1], first_winding_list[1][0][2] - 1], - [first_winding_list[1][-1][0], first_winding_list[1][-1][1], first_winding_list[1][-1][2] - 1], - [second_winding_list[1][0][0], second_winding_list[1][0][1], second_winding_list[1][0][2] - 1], - [second_winding_list[1][-1][0], second_winding_list[1][-1][1], second_winding_list[1][-1][2] - 1], -] -port_dimension_list = [2, dictionary_values[1]["Outer Winding"]["Wire Diameter"]] -for position in port_position_list: - sheet = hfss.modeler.create_rectangle("XZ", position, port_dimension_list, name="sheet_port") - sheet.move([-dictionary_values[1]["Outer Winding"]["Wire Diameter"] / 2, 0, -1]) - hfss.lumped_port(assignment=sheet.name, reference=[ground], - name="port_" + str(port_position_list.index(position) + 1)) - -############################################################################### -# Create mesh -# ~~~~~~~~~~~ -# Create the mesh. - -cylinder_height = 2.5 * dictionary_values[1]["Outer Winding"]["Height"] -cylinder_position = [0, 0, first_winding_list[1][0][2] - 4] -mesh_operation_cylinder = hfss.modeler.create_cylinder("XY", cylinder_position, ground_radius, cylinder_height, - num_sides=36, name="mesh_cylinder") -hfss.mesh.assign_length_mesh([mesh_operation_cylinder], maximum_length=15, maximum_elements=None, name="choke_mesh") - - -############################################################################### -# 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 a setup with a sweep to run the simulation. Depending on your machine's -# computing power, the simulation can take some time to run. - -setup = hfss.create_setup("MySetup") -setup.props["Frequency"] = "50MHz" -setup["MaximumPasses"] = 10 -hfss.create_linear_count_sweep(setup=setup.name, units="MHz", start_frequency=0.1, stop_frequency=100, - num_of_freq_points=100, name="sweep1", save_fields=False, sweep_type="Interpolating") - -############################################################################### -# Save project -# ~~~~~~~~~~~~ -# Save the project. - -hfss.modeler.fit_all() -hfss.plot(show=False, output_file=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=True) - - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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 deleted file mode 100644 index 60e65ae529d..00000000000 --- a/examples/02-HFSS/HFSS_Dipole.py +++ /dev/null @@ -1,220 +0,0 @@ -""" -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 -import ansys.aedt.core - -project_name = ansys.aedt.core.generate_unique_project_name(project_name="dipole") - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical=non_graphical, new_desktop=True) - -############################################################################### -# Launch HFSS -# ~~~~~~~~~~~ -# Launch HFSS 2023 R2 in graphical mode. - -hfss = ansys.aedt.core.Hfss(project=project_name, solution_type="Modal") - -############################################################################### -# Define variable -# ~~~~~~~~~~~~~~~ -# Define a variable for the dipole length. - -hfss["l_dipole"] = "13.5cm" - -############################################################################### -# 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. - -compfile = hfss.components3d["Dipole_Antenna_DM"] -geometryparams = hfss.get_components3d_vars("Dipole_Antenna_DM") -geometryparams["dipole_length"] = "l_dipole" -hfss.modeler.insert_3d_component(compfile, geometryparams) - -############################################################################### -# Create boundaries -# ~~~~~~~~~~~~~~~~~ -# Create boundaries. A region with openings is needed to run the analysis. - -hfss.create_open_region(frequency="1GHz") - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -my_plot = hfss.plot(show=False, plot_air_objects=False) -my_plot.show_axes = False -my_plot.show_grid = False -my_plot.isometric_view = False -my_plot.plot( - os.path.join(hfss.working_directory, "Image.jpg"), -) - -############################################################################### -# Create setup -# ~~~~~~~~~~~~ -# Create a setup with a sweep to run the simulation. - -setup = hfss.create_setup("MySetup") -setup.props["Frequency"] = "1GHz" -setup.props["MaximumPasses"] = 1 -hfss.create_linear_count_sweep(setup=setup.name, units="GHz", start_frequency=0.5, stop_frequency=1.5, - num_of_freq_points=251, name="sweep1", save_fields=False, sweep_type="Interpolating", - interpolation_tol=3, interpolation_max_solutions=255) - -############################################################################### -# Save and run simulation -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Save and run the simulation. - -hfss.analyze_setup("MySetup") - -############################################################################### -# Create scattering plot and far fields report -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a scattering plot and a far fields report. - -hfss.create_scattering("MyScattering") -variations = hfss.available_variations.nominal_w_values_dict -variations["Freq"] = ["1GHz"] -variations["Theta"] = ["All"] -variations["Phi"] = ["All"] -hfss.post.create_report("db(GainTotal)", hfss.nominal_adaptive, variations, primary_sweep_variable="Theta", - report_category="Far Fields", context="3D") - -############################################################################### -# 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. - -new_report = hfss.post.reports_by_category.far_field("db(RealizedGainTotal)", hfss.nominal_adaptive, "3D") -new_report.variations = variations -new_report.primary_sweep = "Theta" -new_report.create("Realized2D") - -############################################################################### -# Generate multiple plots -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Generate multiple plots using the object ``new_report``. This code generates -# 2D and 3D polar plots. - -new_report.report_type = "3D Polar Plot" -new_report.secondary_sweep = "Phi" -new_report.create("Realized3D") - -############################################################################### -# 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 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`` -# method with an arbitrary name. - -hfss["post_x"] = 2 -hfss.variable_manager.set_variable(name="y_post", expression=1, is_post_processing=True) -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. 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") -new_report.primary_sweep = "Theta" -new_report.far_field_sphere = "3D" -solutions = new_report.get_solution_data() - -############################################################################### -# Generate 3D plot using Matplotlib -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Generate a 3D plot using Matplotlib. - -solutions.plot_3d() - -############################################################################### -# 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 a 2D plot using Matplotlib where you specify whether it is a polar -# plot or a rectangular plot. - -solutions.plot() - -########################################################## -# 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. - -ffdata = hfss.get_antenna_data(frequencies=["1000MHz"], setup=hfss.nominal_adaptive, - sphere="Sphere_Custom") - -########################################################## -# Generate 2D cutout plot -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Generate 2D cutout plot. You can define the Theta scan -# and Phi scan. - -ffdata.farfield_data.plot_cut(quantity='RealizedGain', primary_sweep="theta", secondary_sweep_value=0, title='FarField', - quantity_format="dB20", is_polar=True) - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.release_desktop` method. -# All methods provide for saving the project before closing. - -d.release_desktop() diff --git a/examples/02-HFSS/HFSS_FSS_unitcell.py b/examples/02-HFSS/HFSS_FSS_unitcell.py deleted file mode 100644 index a06a97de399..00000000000 --- a/examples/02-HFSS/HFSS_FSS_unitcell.py +++ /dev/null @@ -1,149 +0,0 @@ -""" -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 ansys.aedt.core - -project_name = ansys.aedt.core.generate_unique_project_name(project_name="FSS") - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical=non_graphical, new_desktop=True) - -############################################################################### -# Launch HFSS -# ~~~~~~~~~~~ -# Launch HFSS 2023 R2 in graphical mode. - -hfss = ansys.aedt.core.Hfss(project=project_name, solution_type="Modal") - -############################################################################### -# Define variable -# ~~~~~~~~~~~~~~~ -# Define a variable for the 3D-component. - -hfss["patch_dim"] = "10mm" - -############################################################################### -# Insert 3D component from system library -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Download the 3D component from the example data and insert the 3D Component. - -unitcell_3d_component_path = ansys.aedt.core.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 parameter. - -component_name = hfss.modeler.user_defined_component_names -comp.parameters["a"] = "patch_dim" - -############################################################################### -# 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] -periodicity_y = bounding_dimensions[1] - -region = hfss.modeler.create_air_region( - z_pos=10 * bounding_dimensions[2], - is_percentage=False, - ) - -[x_min, y_min, z_min, x_max, y_max, z_max] = region.bounding_box - -############################################################################### -# Assign Lattice pair boundary -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assigning lattice pair boundary automatically detected. - -hfss.auto_assign_lattice_pairs(assignment=region.name) - -############################################################################### -# Assign Floquet port excitation along +Z direction -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign Floquet port. - -id_z_pos = region.top_face_z -hfss.create_floquet_port(id_z_pos, [0, 0, z_max], [0, y_max, z_max], [x_max, 0, z_max], name='port_z_max', - deembed_distance=10 * bounding_dimensions[2]) - - -############################################################################### -# Create setup -# ~~~~~~~~~~~~ -# Create a setup with a sweep to run the simulation. - -setup = hfss.create_setup("MySetup") -setup.props["Frequency"] = "10GHz" -setup.props["MaximumPasses"] = 10 -hfss.create_linear_count_sweep(setup=setup.name, units="GHz", start_frequency=6, stop_frequency=15, - num_of_freq_points=51, name="sweep1", save_fields=False, sweep_type="Interpolating", - interpolation_tol=6) - -############################################################################### -# 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 = [] - -variation = {"Freq": ["All"]} - -for i in all_quantities: - str_mag.append("mag(" + i + ")") - str_ang.append("ang_deg(" + i + ")") - -hfss.post.create_report(expressions=str_mag, variations=variation, plot_name="magnitude_plot") -hfss.post.create_report(expressions=str_ang, variations=variation, plot_name="phase_plot") - -############################################################################### -# Save and run simulation -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Save and run the simulation. Uncomment the line following line to run the analysis. - -# hfss.analyze() - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.release_desktop` method. -# All methods provide for saving the project before closing. - -hfss.release_desktop() diff --git a/examples/02-HFSS/HFSS_Spiral.py b/examples/02-HFSS/HFSS_Spiral.py deleted file mode 100644 index 52fbf78d76a..00000000000 --- a/examples/02-HFSS/HFSS_Spiral.py +++ /dev/null @@ -1,205 +0,0 @@ -""" -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 ansys.aedt.core - -project_name = ansys.aedt.core.generate_unique_project_name(project_name="spiral") - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################# -# 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 2023 R2 in non-graphical mode and change the -# units to microns. - -hfss = ansys.aedt.core.Hfss(version=aedt_version, non_graphical=non_graphical, design="A1", - new_desktop=True) -hfss.solution_type = "Modal" -hfss.modeler.model_units = "um" -p = hfss.modeler - -############################################################# -# Define variables -# ~~~~~~~~~~~~~~~~ -# Define input variables. You can use the values that follow or edit -# them. - -rin = 10 -width = 2 -spacing = 1 -thickness = 1 -Np = 8 -Nr = 10 -gap = 3 -hfss["Tsub"] = "6" + hfss.modeler.model_units - - -############################################################# -# Standardize polyline -# ~~~~~~~~~~~~~~~~~~~~ -# Standardize the polyline using the ``create_line`` method to fix -# the width, thickness, and material. - -def create_line(pts): - p.create_polyline(pts, material="copper", xsection_type="Rectangle", xsection_width=width, - xsection_height=thickness) - - -################################################################ -# Create spiral inductor -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create the spiral inductor. This spiral inductor is not -# parametric, but you could parametrize it later. - -ind = hfss.modeler.create_spiral( - internal_radius=rin, - width=width, - spacing=spacing, - turns=Nr, - faces=Np, - thickness=thickness, - material="copper", - name="Inductor1", -) - -################################################################ -# Center return path -# ~~~~~~~~~~~~~~~~~~ -# Center the return path. - -x0, y0, z0 = ind.points[0] -x1, y1, z1 = ind.points[-1] -create_line([(x0 - width / 2, y0, -gap), (abs(x1) + 5, y0, -gap)]) -p.create_box([x0 - width / 2, y0 - width / 2, -gap - thickness / 2], [width, width, gap + thickness], material="copper") - -################################################################ -# Create port 1 -# ~~~~~~~~~~~~~ -# Create port 1. - -p.create_rectangle(orientation=ansys.aedt.core.constants.PLANE.YZ, - origin=[abs(x1) + 5, y0 - width / 2, -gap - thickness / 2], - sizes=[width, "-Tsub+{}{}".format(gap, hfss.modeler.model_units)], - name="port1" - ) -hfss.lumped_port(assignment="port1", integration_line=ansys.aedt.core.constants.AXIS.Z) - -################################################################ -# Create port 2 -# ~~~~~~~~~~~~~ -# Create port 2. - -create_line([(x1 + width / 2, y1, 0), (x1 - 5, y1, 0)]) -p.create_rectangle(ansys.aedt.core.constants.PLANE.YZ, [x1 - 5, y1 - width / 2, -thickness / 2], - [width, "-Tsub"], - name="port2") -hfss.lumped_port(assignment="port2", integration_line=ansys.aedt.core.constants.AXIS.Z) - -################################################################ -# 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"], material="silicon") - -p.create_box([x1 - 20, x1 - 20, "-Tsub-{}{}/2".format(thickness, hfss.modeler.model_units)], - [-2 * x1 + 40, -2 * x1 + 40, -0.1], material="PEC") - -################################################################ -# 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], name="airbox", material="air") - -hfss.assign_radiation_boundary_to_objects("airbox") - -################################################################ -# Assign material override -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign a material override so that the validation check does -# not fail. - -hfss.change_material_override() - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -hfss.plot(show=False, output_file=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=False) - -################################################################ -# Create setup -# ~~~~~~~~~~~~ -# Create the setup and define a frequency sweep to solve the project. - -setup1 = hfss.create_setup(name="setup1") -setup1.props["Frequency"] = "10GHz" -hfss.create_linear_count_sweep(setup="setup1", units="GHz", start_frequency=1e-3, stop_frequency=50, - num_of_freq_points=451, sweep_type="Interpolating") -hfss.save_project() -hfss.analyze() - -################################################################ -# 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 -hfss.create_output_variable("L", L_formula, solution="setup1 : LastAdaptive") - -################################################################ -# 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], formula="re", x_label="Freq", y_label="L and Q") - -################################################################ -# 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 the project and close AEDT. - -hfss.save_project(project_name) -hfss.release_desktop() diff --git a/examples/02-HFSS/HFSS_eigenmode.py b/examples/02-HFSS/HFSS_eigenmode.py deleted file mode 100644 index 0c931041605..00000000000 --- a/examples/02-HFSS/HFSS_eigenmode.py +++ /dev/null @@ -1,162 +0,0 @@ -""" -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 ansys.aedt.core - -# Create a temporary folder to download the example to. - -temp_folder = ansys.aedt.core.generate_unique_folder_name() -project_path = ansys.aedt.core.downloads.download_file("eigenmode", "emi_PCB_house.aedt", temp_folder) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical=non_graphical, new_desktop=True) - -############################################################################### -# Launch HFSS -# ~~~~~~~~~~~ -# Launch HFSS 2023 R2 in graphical mode. - -hfss = ansys.aedt.core.Hfss(project=project_path, non_graphical=non_graphical) - -############################################################################### -# 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 -# eigenmode solver needs to converge on modes. ``fmin`` is the lowest frequency -# 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 -next_fmin = fmin -setup_nr = 1 - -limit = 10 -resonance = {} - - -############################################################################### -# 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" - setup_name = "em_setup" + str(setup_nr) - setup = hfss.create_setup(setup_name) - setup.props['MinimumFrequency'] = next_min_freq - setup.props['NumModes'] = num_modes - setup.props['ConvergeOnRealFreq'] = True - setup.props['MaximumPasses'] = 10 - setup.props['MinimumPasses'] = 3 - setup.props['MaxDeltaFreq'] = 5 - # analyzing the eigenmode setup - hfss.analyze_setup(setup_name, cores=8, use_auto_settings=True) - # getting the Q and real frequency of each mode - eigen_q = hfss.post.available_report_quantities(quantities_category="Eigen Q") - eigen_mode = hfss.post.available_report_quantities() - data = {} - cont = 0 - for i in eigen_mode: - eigen_q_value = hfss.post.get_solution_data(expressions=eigen_q[cont], - setup_sweep_name=setup_name + ' : LastAdaptive', - report_category="Eigenmode") - eigen_mode_value = hfss.post.get_solution_data(expressions=eigen_mode[cont], - setup_sweep_name=setup_name + ' : LastAdaptive', - report_category="Eigenmode") - data[cont] = [eigen_q_value.data_real()[0], eigen_mode_value.data_real()[0]] - cont += 1 - - print(data) - return data - - -############################################################################### -# 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 - setup_nr += 1 - cont_res = len(resonance) - for q in output: - if output[q][0] > limit: - resonance[cont_res] = output[q] - cont_res += 1 - -resonance_frequencies = [f"{resonance[i][1] / 1e9:.5} GHz" for i in resonance] -print(str(resonance_frequencies)) - -############################################################################### -# Save project -# ~~~~~~~~~~~~ -# Save the project. - -hfss.modeler.fit_all() -hfss.plot(show=False, output_file=os.path.join(hfss.working_directory, "Image.jpg"), plot_air_objects=False) - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Save the project and close AEDT. - -hfss.save_project() -hfss.release_desktop() diff --git a/examples/02-HFSS/Probe_Fed_Patch.py b/examples/02-HFSS/Probe_Fed_Patch.py deleted file mode 100644 index 57eda273244..00000000000 --- a/examples/02-HFSS/Probe_Fed_Patch.py +++ /dev/null @@ -1,119 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~ - -import os - -import ansys.aedt.core -import tempfile -from ansys.aedt.core.modeler.advanced_cad.stackup_3d import Stackup3D - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. ``"PYAEDT_NON_GRAPHICAL"`` is set to ``False`` -# to create this documentation. -# -# You can set ``non_graphical`` to ``True`` to view -# HFSS while the notebook cells are executed. - -non_graphical = False -length_units = "mm" -freq_units = "GHz" - -######################################################## -# Create temporary working folder -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Use tempfile to create a temporary working folder. Project data -# is deleted after this example is run. -# -# To save the project data in another location, change -# the location of the project directory. -# - -# tmpdir.cleanup() at the end of this notebook removes all -# project files and data. - -tmpdir = tempfile.TemporaryDirectory(suffix="_aedt") -project_folder = tmpdir.name -proj_name = os.path.join(project_folder, "antenna") - -##################### -# Launch HFSS -# ----------- -# - -hfss = ansys.aedt.core.Hfss(project=proj_name, - solution_type="Terminal", - design="patch", - non_graphical=non_graphical, - new_desktop=True, - version=aedt_version) - -hfss.modeler.model_units = length_units - -##################################### -# 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)") -signal = stackup.add_signal_layer("signal", material="copper", thickness=0.035, fill_material="air") -patch = signal.add_patch(patch_length=9.57, patch_width=9.25, - patch_name="Patch", frequency=1E10) - -stackup.resize_around_element(patch) -pad_length = [3, 3, 3, 3, 3, 3] # Air bounding box buffer in mm. -region = hfss.modeler.create_region(pad_length, is_percentage=False) -hfss.assign_radiation_boundary_to_objects(region.name) - -patch.create_probe_port(ground, rel_x_offset=0.485) -setup = hfss.create_setup(name="Setup1", - setup_type="HFSSDriven", - Frequency="10GHz") - -setup.create_frequency_sweep(unit="GHz", - name="Sweep1", - start_frequency=8, - stop_frequency=12, - sweep_type="Interpolating") - -hfss.save_project() -hfss.analyze() - -############################### -# 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 and clean up temporary folders and files. - -hfss.release_desktop() -tmpdir.cleanup() 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 deleted file mode 100644 index 4ac4aa249d2..00000000000 --- a/examples/02-HFSS/Waveguide_Filter.py +++ /dev/null @@ -1,242 +0,0 @@ -""" -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. -# - -import os -import tempfile -import ansys.aedt.core -from ansys.aedt.core import general_methods - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Launch Ansys Electronics Desktop (AEDT) -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# - -############################################################################### -# 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. -# a: Long dimension of the waveguide cross-section (X-Band) -# 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, - 'b': 0.9, - 't': 0.15, - 'units': 'in'} - -non_graphical = False -new_thread = True - -############################################################################### -# 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): - os.mkdir(project_folder) -project_name = os.path.join(project_folder, general_methods.generate_unique_name("wgf", n=2)) - -# Instantiate the HFSS application -hfss = ansys.aedt.core.Hfss(project=project_name + '.aedt', - version=aedt_version, - design="filter", - non_graphical=non_graphical, - new_desktop=True, - close_on_exit=True, - solution_type="Modal") - -# hfss.settings.enable_debug_methods_argument_logger = False # Only for debugging. - -var_mapping = dict() # Used by parse_expr to parse expressions. - -############################################################################### -# Initialize design parameters in HFSS. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -hfss.modeler.model_units = "in" # Set to inches -for key in wgparams: - if type(wgparams[key]) in [int, float]: - hfss[key] = str(wgparams[key]) + wgparams['units'] - var_mapping[key] = wgparams[key] # Used for expression parsing - elif type(wgparams[key]) == list: - count = 1 - for v in wgparams[key]: - this_key = key + str(count) - hfss[this_key] = str(v) + wgparams['units'] - var_mapping[this_key] = v # Used to parse expressions and generate numerical values. - count += 1 - -if len(wgparams['l']) % 2 == 0: - zstart = "-t/2" # Even number of cavities, odd number of irises. - is_even = True -else: - zstart = "l1/2 - t/2" # Odd number of cavities, even number of irises. - is_even = False - - -############################################################################### -# 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. - -def place_iris(zpos, dz, n): - w_str = "w" + str(n) # Iris width parameter as a string. - this_name = "iris_a_" + str(n) # Iris object name in the HFSS project. - iris = [] # Return a list of the two objects that make up the iris. - if this_name in hfss.modeler.object_names: - this_name = this_name.replace("a", "c") - iris.append(hfss.modeler.create_box(origin=['-b/2', '-a/2', zpos], - sizes=['(b - ' + w_str + ')/2', 'a', dz], - name=this_name, - material="silver")) - iris.append(iris[0].mirror([0, 0, 0], [1, 0, 0], duplicate=True)) - return iris - - -############################################################################### -# 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] - iris = place_iris(zpos, "t", count) - iris = place_iris("-(" + zpos + ")", "-t", count) - - else: # Place first iris - zpos = zstart - iris = place_iris(zpos, "t", count) - if not is_even: - iris = place_iris("-(" + zpos + ")", "-t", count) - -############################################################################### -# Draw full waveguide with ports -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Use ``hfss.variable_manager`` which acts like a dict() to return an instance of -# the ``ansys.aedt.core.application.variables.VariableManager`` class for any variable. -# The ``VariableManager`` instance takes the HFSS variable name as a key. -# ``VariableManager`` properties enable access to update, modify and -# evaluate variables. - -var_mapping['port_extension'] = 1.5 * wgparams['l'][0] -hfss['port_extension'] = str(var_mapping['port_extension']) + wgparams['units'] -hfss["wg_z_start"] = "-(" + zpos + ") - port_extension" -hfss["wg_length"] = "2*(" + zpos + " + port_extension )" -wg_z_start = hfss.variable_manager["wg_z_start"] -wg_length = hfss.variable_manager["wg_length"] -hfss["u_start"] = "-a/2" -hfss["u_end"] = "a/2" -hfss.modeler.create_box(origin=["-b/2", "-a/2", "wg_z_start"], - sizes=["b", "a", "wg_length"], - name="waveguide", - material="vacuum") - -############################################################################### -# 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 -# and define the calibration lines to ensure self-consistent -# polarization between wave ports. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -count = 0 -ports = [] -for n, z in enumerate(wg_z): - face_id = hfss.modeler.get_faceid_from_position(position=[0, 0, z], assignment="waveguide") - u_start = [0, hfss.variable_manager["u_start"].evaluated_value, z] - 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. -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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) - -setup.create_frequency_sweep( - unit="GHz", - name="Sweep1", - start_frequency=9.5, - stop_frequency=10.5, - sweep_type="Interpolating", -) - -################################################################################# -# Solve the project with two tasks. -# Each frequency point is solved simultaneously. - - -setup.analyze(tasks=2) - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~~ -# The following command generates a field plot in HFSS and uses PyVista -# to plot the field in Jupyter. - -plot = hfss.post.plot_field(quantity="Mag_E", assignment=["Global:XZ"], plot_type="CutPlane", - setup=hfss.nominal_adaptive, intrinsics={"Freq": "9.8GHz", "Phase": "0deg"}, show=False, - export_path=hfss.working_directory) - -############################################################################### -# Save and close the desktop -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# The following command saves the project to a file and closes the desktop. - -hfss.save_project() -hfss.release_desktop() diff --git a/examples/02-SBR+/Readme.txt b/examples/02-SBR+/Readme.txt deleted file mode 100644 index edb3b62f744..00000000000 --- a/examples/02-SBR+/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -SBR+ examples -~~~~~~~~~~~~~ -These examples use PyAEDT to show some end-to-end workflows for HFSS SBR+. -This includes model generation, setup, meshing, and postprocessing. diff --git a/examples/02-SBR+/SBR_City_Import.py b/examples/02-SBR+/SBR_City_Import.py deleted file mode 100644 index 4384fe2ad31..00000000000 --- a/examples/02-SBR+/SBR_City_Import.py +++ /dev/null @@ -1,80 +0,0 @@ -""" -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 ansys.aedt.core import Hfss - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Define designs -# ~~~~~~~~~~~~~~ -# Define two designs, one source and one target. -# Each design is connected to a different object. - -app = Hfss( - design="Ansys", - solution_type="SBR+", - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical -) - -############################################################################### -# Define Location to import -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define latitude and longitude to import. -ansys_home = [40.273726, -80.168269] - -############################################################################### -# Generate map and import -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Assign boundaries. - -app.modeler.import_from_openstreet_map(ansys_home, - terrain_radius=250, - road_step=3, - plot_before_importing=False, - import_in_aedt=True) - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -plot_obj = app.plot(show=False, plot_air_objects=True) -plot_obj.background_color = [153,203,255] -plot_obj.zoom = 1.5 -plot_obj.show_grid = False -plot_obj.show_axes = False -plot_obj.bounding_box = False -plot_obj.plot(os.path.join(app.working_directory, "Source.jpg")) - -############################################################################### -# 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 deleted file mode 100644 index f41f1976e35..00000000000 --- a/examples/02-SBR+/SBR_Doppler_Example.py +++ /dev/null @@ -1,139 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -# Launch AEDT -# ~~~~~~~~~~~ -# Launch AEDT. - -projectname = "MicroDoppler_with_ADP" -designname = "doppler" -library_path = ansys.aedt.core.downloads.download_multiparts() - -############################################################################### -# 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 the project. - -project_name = ansys.aedt.core.generate_unique_project_name(project_name="doppler") - -# Instantiate the application. -app = ansys.aedt.core.Hfss( - version=aedt_version, - solution_type="SBR+", - new_desktop=True, - project=project_name, - close_on_exit=True, - non_graphical=non_graphical -) - -app.autosave_disable() - -############################################################################### -# 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 to 3D components. - -actor_lib = os.path.join(library_path, "actor_library") -env_lib = os.path.join(library_path, "environment_library") -radar_lib = os.path.join(library_path, "radar_modules") -env_folder = os.path.join(env_lib, "road1") -person_folder = os.path.join(actor_lib, "person3") -car_folder = os.path.join(actor_lib, "vehicle1") -bike_folder = os.path.join(actor_lib, "bike1") -bird_folder = os.path.join(actor_lib, "bird1") - -############################################################################### -# Define environment -# ~~~~~~~~~~~~~~~~~~ -# Define the background environment. - -road1 = app.modeler.add_environment(input_dir=env_folder, name="Bari") -prim = app.modeler - -############################################################################### -# Place actors -# ~~~~~~~~~~~~ -# Place actors in the environment. This code places persons, birds, bikes, and cars -# in the environment. - -person1 = app.modeler.add_person(input_dir=person_folder, speed=1.0, global_offset=[25, 1.5, 0], yaw=180, - name="Massimo") -person2 = app.modeler.add_person(input_dir=person_folder, speed=1.0, global_offset=[25, 2.5, 0], yaw=180, name="Devin") -car1 = app.modeler.add_vehicle(input_dir=car_folder, speed=8.7, global_offset=[3, -2.5, 0], name="LuxuryCar") -bike1 = app.modeler.add_vehicle(input_dir=bike_folder, speed=2.1, global_offset=[24, 3.6, 0], yaw=180, - name="Alberto_in_bike") -bird1 = app.modeler.add_bird(input_dir=bird_folder, speed=1.0, global_offset=[19, 4, 3], yaw=120, pitch=-5, - flapping_rate=30, name="Pigeon") -bird2 = app.modeler.add_bird(input_dir=bird_folder, speed=1.0, global_offset=[6, 2, 3], yaw=-60, pitch=10, name="Eagle") - -############################################################################### -# Place radar -# ~~~~~~~~~~~ -# Place radar on the car. The radar is created relative to the car's coordinate -# system. - -radar1 = app.create_sbr_radar_from_json(radar_file=radar_lib, name="Example_1Tx_1Rx", offset=[2.57, 0, 0.54], - use_relative_cs=True, relative_cs_name=car1.cs_name) - -############################################################################### -# 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. - -setup, sweep = app.create_sbr_pulse_doppler_setup(sweep_time_duration=2) -app.set_sbr_current_sources_options() -app.validate_simple() - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -app.plot(show=False, output_file=os.path.join(app.working_directory, "Image.jpg"), plot_air_objects=True) - -############################################################################### -# Solve and release AEDT -# ~~~~~~~~~~~~~~~~~~~~~~ -# Solve and release AEDT. To solve, uncomment the ``app.analyze_setup`` command -# to activate the simulation. - -# app.analyze_setup(sweep.name) -app.save_project() -app.release_desktop(close_projects=True, close_desktop=True) diff --git a/examples/02-SBR+/SBR_Example.py b/examples/02-SBR+/SBR_Example.py deleted file mode 100644 index 389ee306719..00000000000 --- a/examples/02-SBR+/SBR_Example.py +++ /dev/null @@ -1,122 +0,0 @@ -""" -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. - -import os -import ansys.aedt.core - -project_full_name = ansys.aedt.core.downloads.download_sbr(ansys.aedt.core.generate_unique_project_name(project_name="sbr_freq")) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Define designs -# ~~~~~~~~~~~~~~ -# Define two designs, one source and one target, with each design connected to -# a different object. - -target = ansys.aedt.core.Hfss( - project=project_full_name, - design="Cassegrain_", - solution_type="SBR+", - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical -) - -source = ansys.aedt.core.Hfss(project=target.project_name, - design="feeder", - version=aedt_version, - ) - -############################################################################### -# 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", field_type="farfield") - -############################################################################### -# Assign boundaries -# ~~~~~~~~~~~~~~~~~ -# Assign boundaries. - -target.assign_perfecte_to_sheets(["Reflector", "Subreflector"]) -target.mesh.assign_curvilinear_elements(["Reflector", "Subreflector"]) - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model - -source.plot(show=False, output_file=os.path.join(target.working_directory, "Source.jpg"), plot_air_objects=True) -target.plot(show=False, output_file=os.path.join(target.working_directory, "Target.jpg"), plot_air_objects=False) - -############################################################################### -# Create setup and solve -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a setup and solve it. - -setup1 = target.create_setup() -setup1.props["RadiationSetup"] = "ATK_3D" -setup1.props["ComputeFarFields"] = True -setup1.props["RayDensityPerWavelength"] = 2 -setup1.props["MaxNumberOfBounces"] = 3 -setup1["RangeType"] = "SinglePoints" -setup1["RangeStart"] = "10GHz" -target.analyze() - -############################################################################### -# Plot results -# ~~~~~~~~~~~~ -# Plot results. - -variations = target.available_variations.nominal_w_values_dict -variations["Freq"] = ["10GHz"] -variations["Theta"] = ["All"] -variations["Phi"] = ["All"] -target.post.create_report("db(GainTotal)", target.nominal_adaptive, variations=variations, - primary_sweep_variable="Theta", report_category="Far Fields", context="ATK_3D") - -############################################################################### -# Plot results outside AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Plot results using Matplotlib. - -solution = target.post.get_solution_data( - "GainTotal", - target.nominal_adaptive, - variations=variations, - primary_sweep_variable="Theta", - context="ATK_3D", - report_category="Far Fields", -) -solution.plot() - -############################################################################### -# 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 deleted file mode 100644 index 01a391164d9..00000000000 --- a/examples/02-SBR+/SBR_Time_Plot.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -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 ansys.aedt.core import Hfss, downloads - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the project. - -project_file = downloads.download_sbr_time() - -hfss = Hfss(project=project_file, version=aedt_version, non_graphical=non_graphical, new_desktop=True) - -hfss.analyze() - -############################################################################### -# Get solution data -# ~~~~~~~~~~~~~~~~~ -# Get solution data. After simulation is performed, you can load solutions -# in the ``solution_data`` object. - -solution_data = hfss.post.get_solution_data(expressions=["NearEX", "NearEY", "NearEZ"], - variations={"_u": ["All"], "_v": ["All"], "Freq": ["All"]}, - context="Near_Field", - report_category="Near Fields") - -############################################################################### -# Compute IFFT -# ~~~~~~~~~~~~ -# Compute IFFT (Inverse Fast Fourier Transform). - -t_matrix = solution_data.ifft("NearE", window=True) - - -############################################################################### -# 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_path=os.path.join(hfss.working_directory, "csv")) - -############################################################################### -# Plot scene -# ~~~~~~~~~~ -# Plot the scene to create the time plot animation - -hfss.post.plot_scene(frames=frames_list_file, gif_path=os.path.join(hfss.working_directory, "animation.gif"), - norm_index=15, dy_rng=35, show=False, view="xy", zoom=1) - -hfss.release_desktop() diff --git a/examples/03-Maxwell/Maxwell2D_DCConduction.py b/examples/03-Maxwell/Maxwell2D_DCConduction.py deleted file mode 100644 index 05e4861fefd..00000000000 --- a/examples/03-Maxwell/Maxwell2D_DCConduction.py +++ /dev/null @@ -1,270 +0,0 @@ -""" -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 - -import ansys.aedt.core - -from ansys.aedt.core.post.pdf import AnsysReport - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -################################################################################## -# 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``. - -m2d = ansys.aedt.core.Maxwell2d( - version=aedt_version, - new_desktop=True, - close_on_exit=True, - solution_type="DCConduction", - project="M2D_DC_Conduction", - design="Ansys_resistor" -) - -########################################################## -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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 = ansys.aedt.core.downloads.download_file("dxf", "Ansys_logo_2D.dxf") -# dxf_layers = m2d.get_dxf_layers(DXFPath) -# m2d.import_dxf(DXFPath, dxf_layers, scale=1E-05) - -parasolid_path = ansys.aedt.core.downloads.download_file("x_t", "Ansys_logo_2D.x_t") -m2d.modeler.import_3d_cad(parasolid_path) - -################################################################################## -# Define variables -# ~~~~~~~~~~~~~~~~ -# Define conductor thickness in z-direction, material array with 4 materials, -# and MaterialIndex referring to the material array - -m2d["MaterialThickness"] = "5mm" -m2d["ConductorMaterial"] = "[\"Copper\", \"Aluminum\", \"silver\", \"gold\"]" -MaterialIndex = 0 -m2d["MaterialIndex"] = str(MaterialIndex) -no_materials = 4 - - -################################################################################## -# Assign materials -# ~~~~~~~~~~~~~~~~ -# A voltage port is defined as a perfect electric conductor (pec). A conductor -# gets the material defined by the 0th entry of the material array. - -m2d.assign_material(["ANSYS_LOGO_2D_1", "ANSYS_LOGO_2D_2"], "gold") -m2d.modeler["ANSYS_LOGO_2D_3"].material_name = "ConductorMaterial[MaterialIndex]" - -################################################################################## -# 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 - -m2d.assign_matrix(assignment=['1V'], matrix_name="Matrix1", group_sources=['0V']) - -################################################################################## -# Assign mesh operation -# ~~~~~~~~~~~~~~~~~~~~~ -# 3mm on the conductor - -m2d.mesh.assign_length_mesh(["ANSYS_LOGO_2D_3"], maximum_length=3, maximum_elements=None, name="conductor") - -################################################################################## -# 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. - -setup1 = m2d.create_setup(name="Setup1", MinimumPasses=4) -setup1.enable_expression_cache( # doesn't work? - report_type="DCConduction", - expressions="1/Matrix1.G(1V,1V)/MaterialThickness", - isconvergence=True, - conv_criteria=1, - use_cache_for_freq=False) -setup1.analyze() - -################################################################################## -# 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. - -param_sweep = m2d.parametrics.add("MaterialIndex", 0, no_materials - 1, 1, "LinearStep", name="MaterialSweep") -param_sweep["SaveFields"] = True -param_sweep["CopyMesh"] = True -param_sweep["SolveWithCopiedMeshOnly"] = True -param_sweep.analyze() - -################################################################################## -# 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", variations=variations, - primary_sweep_variable="MaterialIndex", report_category="DCConduction", - plot_type="Data Table", plot_name="Resistance vs. Material") - -############################################################################### -# Get solution data -# ~~~~~~~~~~~~~~~~~ -# Get solution data using the object ``report``` to get resistance values -# and plot data outside AEDT. - -d = report.get_solution_data() -resistence = d.data_magnitude() -material_index = d.primary_sweep_values -d.primary_sweep = "MaterialIndex" -d.plot(snapshot_path=os.path.join(results_folder, "M2D_DCConduction.jpg")) - -############################################################################### -# Create material index vs resistance table -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create material index vs resistance table to use in PDF report generator. -# Create ``colors`` table to customize each row of the material index vs resistance table. - -material_index_vs_resistance = [["Material", "Resistance"]] -colors = [[(255, 255, 255), (0, 255, 0)]] -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 - -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 - -py_vista_plot = m2d.post.plot_field("Mag_E", conductor_surface, show=False, plot_cad_objs=False) -py_vista_plot.isometric_view = False -py_vista_plot.camera_position = [0, 0, 7] -py_vista_plot.focal_point = [0, 0, 0] -py_vista_plot.roll_angle = 0 -py_vista_plot.elevation_angle = 0 -py_vista_plot.azimuth_angle = 0 -py_vista_plot.plot(os.path.join(results_folder, "mag_E.jpg")) - -################################################################################## -# Field animation -# ~~~~~~~~~~~~~~~ -# Plot current density vs the Material index. - -animated = m2d.post.plot_animated_field(quantity="Mag_J", assignment=conductor_surface, - variation_variable="MaterialIndex", variations=[0, 1, 2, 3], - show=False, log_scale=True, export_gif=False, - export_path=results_folder) -animated.isometric_view = False -animated.camera_position = [0, 0, 7] -animated.focal_point = [0, 0, 0] -animated.roll_angle = 0 -animated.elevation_angle = 0 -animated.azimuth_angle = 0 -animated.animate() - -################################################################################ -# Export model picture -# ~~~~~~~~~~~~~~~~~~~~ -# Export model picture. - -model_picture = m2d.post.export_model_picture() - -################################################################################ -# Generate PDF report -# ~~~~~~~~~~~~~~~~~~~ -# Generate a PDF report with output of simulation. - -pdf_report = AnsysReport(version=aedt_version, design_name=m2d.design_name, project_name=m2d.project_name) - -# Customize text font. - -pdf_report.report_specs.font = "times" -pdf_report.report_specs.text_font_size = 10 - -# Create report - -pdf_report.create() - -# Add project's design info to report. - -pdf_report.add_project_info(m2d) - -# Add model picture in a new chapter and add text. - -pdf_report.add_chapter("Model Picture") -pdf_report.add_text("This section contains the model picture") -pdf_report.add_image(model_picture, "Model Picture", width=80, height=60) - -# Add in a new chapter field overlay plots. - -pdf_report.add_chapter("Field overlay") -pdf_report.add_sub_chapter("Plots") -pdf_report.add_text("This section contains the fields overlay.") -pdf_report.add_image(os.path.join(results_folder, "mag_E.jpg"), "Mag E", width=120, height=80) -pdf_report.add_page_break() - -# Add a new section to display results. - -pdf_report.add_section() -pdf_report.add_chapter("Results") -pdf_report.add_sub_chapter("Resistance vs. Material") -pdf_report.add_text("This section contains resistance vs material data.") -# Aspect ratio is automatically calculated if only width is provided -pdf_report.add_image(os.path.join(results_folder, "M2D_DCConduction.jpg"), width=130) - -# Add a new subchapter to display resistance data from previously created table. - -pdf_report.add_sub_chapter("Resistance data table") -pdf_report.add_text("This section contains Resistance data.") -pdf_report.add_table("Resistance Data", content=material_index_vs_resistance, formatting=colors, col_widths=[75, 100]) - -# Add table of content and save PDF. - -pdf_report.add_toc() -pdf_report.save_pdf(results_folder, "AEDT_Results.pdf") - -################################################################################## -# Release desktop -# ~~~~~~~~~~~~~~~ - -m2d.release_desktop() diff --git a/examples/03-Maxwell/Maxwell2D_Electrostatic.py b/examples/03-Maxwell/Maxwell2D_Electrostatic.py deleted file mode 100644 index be36f0081c6..00000000000 --- a/examples/03-Maxwell/Maxwell2D_Electrostatic.py +++ /dev/null @@ -1,214 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -################################################################################# -# Initialize Maxwell 2D -# ~~~~~~~~~~~~~~~~~~~~~ -# Initialize Maxwell 2D, providing the version, path to the project, and the design -# name and type. - -setup_name = 'MySetupAuto' -solver = 'Electrostatic' -design_name = 'Design1' -project_name = ansys.aedt.core.generate_unique_project_name() -non_graphical = False - -################################################################################# -# Download .xlsx file -# ~~~~~~~~~~~~~~~~~~~ -# Set local temporary folder to export the .xlsx file to. - -file_name_xlsx = ansys.aedt.core.downloads.download_file("field_line_traces", "my_copper.xlsx") - -################################################################################# -# Initialize dictionaries -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize dictionaries that contain all the definitions for the design variables. - -geom_params_circle = { - 'circle_x0': '-10mm', - 'circle_y0': '0mm', - 'circle_z0': '0mm', - 'circle_axis': 'Z', - 'circle_radius': '1mm' -} - -geom_params_rectangle = { - 'r_x0': '1mm', - 'r_y0': '5mm', - 'r_z0': '0mm', - 'r_axis': 'Z', - 'r_dx': '-1mm', - 'r_dy': '-10mm' -} - -################################################################################## -# Launch Maxwell 2D -# ~~~~~~~~~~~~~~~~~ -# Launch Maxwell 2D and save the project. - -M2D = ansys.aedt.core.Maxwell2d(project=project_name, - version=aedt_version, - design=design_name, - solution_type=solver, - new_desktop=True, - non_graphical=non_graphical - ) - -################################################################################## -# 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 design variables from the created dictionaries. - -for k, v in geom_params_circle.items(): - M2D[k] = v -for k, v in geom_params_rectangle.items(): - M2D[k] = v - -################################################################################## -# 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 rectangle and a circle and assign the material read from the .xlsx file. -# Create two new polylines and a region. - -rect = mod2D.create_rectangle(origin=['r_x0', 'r_y0', 'r_z0'], - sizes=['r_dx', 'r_dy', 0], - name='Ground', matname=mats[0]) -rect.color = (0, 0, 255) # rgb -rect.solve_inside = False - -circle = mod2D.create_circle(position=['circle_x0', 'circle_y0', 'circle_z0'], radius='circle_radius', - num_sides='0', is_covered=True, name='Electrode', matname=mats[0]) -circle.color = (0, 0, 255) # rgb -circle.solve_inside = False - -poly1_points = [[-9, 2, 0], [-4, 2, 0], [2, -2, 0],[8, 2, 0]] -poly2_points = [[-9, 0, 0], [9, 0, 0]] -poly1_id = mod2D.create_polyline(points=poly1_points, segment_type='Spline', name='Poly1') -poly2_id = mod2D.create_polyline(points=poly2_points, name='Poly2') -mod2D.split([poly1_id, poly2_id], 'YZ', sides='NegativeOnly') -mod2D.create_region([20, 100, 20, 100]) - -################################################################################## -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign a surface mesh to the rectangle. - -M2D.mesh.assign_surface_mesh_manual(assignment=['Ground'], surface_deviation=0.001) - -################################################################################## -# Create, validate and analyze the setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create, update, validate and analyze the setup. - -setup = M2D.create_setup(name=setup_name) -setup.props['PercentError'] = 0.5 -setup.update() -M2D.validate_simple() -M2D.analyze_setup(setup_name) - -################################################################################## -# 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. - -fields = M2D.ofieldsreporter -fields.CalcStack("clear") -fields.EnterQty("E") -fields.EnterEdge("Poly1") -fields.CalcOp("Tangent") -fields.CalcOp("Dot") -fields.AddNamedExpression("e_tan_poly1", "Fields") -fields.EnterQty("E") -fields.EnterEdge("Poly2") -fields.CalcOp("Tangent") -fields.CalcOp("Dot") -fields.AddNamedExpression("e_tan_poly2", "Fields") - -################################################################################## -# 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. - -plot = M2D.post.create_fieldplot_line_traces(seeding_faces=["Ground", "Electrode", "Region"], - in_volume_tracing_objs="Region", plot_name="LineTracesTest") - -################################################################################### -# Update Field Line Traces Plot -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Update field line traces plot. -# Update seeding points number, line style and line width. - -plot.SeedingPointsNumber = 20 -plot.LineStyle = "Cylinder" -plot.LineWidth = 3 -plot.update() - -################################################################################### -# Export field line traces plot -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Export field line traces plot. -# For field lint traces plot, the export file format is ``.fldplt``. - -M2D.post.export_field_plot(plot_name="LineTracesTest", output_dir=M2D.toolkit_directory, file_format="fldplt") - -########################################################## -# Export the mesh field plot -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Export the mesh in ``aedtplt`` format. - -M2D.post.export_mesh_obj(setup=M2D.nominal_adaptive) - -################################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Save the project and close AEDT. - -M2D.save_project() -M2D.release_desktop() diff --git a/examples/03-Maxwell/Maxwell2D_PMSynchronousMotor.py b/examples/03-Maxwell/Maxwell2D_PMSynchronousMotor.py deleted file mode 100644 index d06a1442d0a..00000000000 --- a/examples/03-Maxwell/Maxwell2D_PMSynchronousMotor.py +++ /dev/null @@ -1,759 +0,0 @@ -""" -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 - -import csv -import os -import ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -################################################################################# -# Initialize Maxwell 2D -# ~~~~~~~~~~~~~~~~~~~~~ -# Initialize Maxwell 2D, providing the version, path to the project, and the design -# name and type. - -setup_name = "MySetupAuto" -solver = "TransientXY" - -project_name = ansys.aedt.core.generate_unique_project_name() -design_name = "Sinusoidal" - -################################################################################# -# Initialize definitions for stator, rotor, and shaft -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize geometry parameter definitions for the stator, rotor, and shaft. -# The naming refers to RMxprt primitives. - -geom_params = { - "DiaGap": "132mm", - "DiaStatorYoke": "198mm", - "DiaStatorInner": "132mm", - "DiaRotorLam": "130mm", - "DiaShaft": "44.45mm", - "DiaOuter": "198mm", - "Airgap": "1mm", - "SlotNumber": "48", - "SlotType": "3" -} - -################################################################################# -# Initialize definitions for stator windings -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize geometry parameter definitions for the stator windings. The naming -# refers to RMxprt primitives. - -wind_params = { - "Layers": "1", - "ParallelPaths": "2", - "R_Phase": "7.5mOhm", - "WdgExt_F": "5mm", - "SpanExt": "30mm", - "SegAngle": "0.25", - "CoilPitch": "5", # coil pitch in slots - "Coil_SetBack": "3.605732823mm", - "SlotWidth": "2.814mm", # RMxprt Bs0 - "Coil_Edge_Short": "3.769235435mm", - "Coil_Edge_Long": "15.37828521mm" -} - -################################################################################# -# Initialize definitions for model setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize geometry parameter definitions for the model setup. - -mod_params = { - "NumPoles": "8", - "Model_Length": "80mm", - "SymmetryFactor": "8", - "Magnetic_Axial_Length": "150mm", - "Stator_Lam_Length": "0mm", - "StatorSkewAngle": "0deg", - "NumTorquePointsPerCycle": "30", - "mapping_angle": "0.125*4deg", - "num_m": "16", - "Section_Angle": "360deg/SymmetryFactor" -} - -################################################################################# -# Initialize definitions for operational machine -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize geometry parameter definitions for the operational machine. This -# identifies the operating point for the transient setup. - -oper_params = { - "InitialPositionMD": "180deg/4", - "IPeak": "480A", - "MachineRPM": "3000rpm", - "ElectricFrequency": "MachineRPM/60rpm*NumPoles/2*1Hz", - "ElectricPeriod": "1/ElectricFrequency", - "BandTicksinModel": "360deg/NumPoles/mapping_angle", - "TimeStep": "ElectricPeriod/(2*BandTicksinModel)", - "StopTime": "ElectricPeriod", - "Theta_i": "135deg" -} - -########################################################## -# 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 and save the project. - -M2D = ansys.aedt.core.Maxwell2d(project=project_name, - version=aedt_version, - design=design_name, - solution_type=solver, - new_desktop=True, - non_graphical=non_graphical - ) - -########################################################## -# 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 design variables from the created dictionaries. - -for k, v in geom_params.items(): - M2D[k] = v -for k, v in wind_params.items(): - M2D[k] = v -for k, v in mod_params.items(): - M2D[k] = v -for k, v in oper_params.items(): - M2D[k] = v - -########################################################## -# 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 = ansys.aedt.core.downloads.download_leaf() - -########################################################## -# Create first material -# ~~~~~~~~~~~~~~~~~~~~~ -# Create the material ``"Copper (Annealed)_65C"``. - -mat_coils = M2D.materials.add_material("Copper (Annealed)_65C") -mat_coils.update() -mat_coils.conductivity = "49288048.9198" -mat_coils.permeability = "1" - -########################################################## -# 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`` -# method. - -mat_PM = M2D.materials.add_material("Arnold_Magnetics_N30UH_80C_new") -mat_PM.update() -mat_PM.conductivity = "555555.5556" -mat_PM.set_magnetic_coercivity(value=-800146.66287534, x=1, y=0, z=0) -mat_PM.mass_density = "7500" -BH_List_PM = [] -with open(filename_PM) as f: - reader = csv.reader(f, delimiter='\t') - next(reader) - for row in reader: - BH_List_PM.append([float(row[0]), float(row[1])]) -mat_PM.permeability.value = BH_List_PM - -########################################################## -# 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. - -mat_lam = M2D.materials.add_material("30DH_20C_smooth") -mat_lam.update() -mat_lam.conductivity = "1694915.25424" -kh = 71.7180985413 -kc = 0.25092214579 -ke = 12.1625774023 -kdc = 0.001 -eq_depth = 0.001 -mat_lam.set_electrical_steel_coreloss(kh, kc, ke, kdc, eq_depth) -mat_lam.mass_density = "7650" -BH_List_lam = [] -with open(filename_lam) as f: - reader = csv.reader(f, delimiter='\t') - next(reader) - for row in reader: - BH_List_lam.append([float(row[0]), float(row[1])]) -mat_lam.permeability.value = BH_List_lam - -########################################################## -# 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"], - ["Hs2", "17.287669825502mm"], - ["Bs0", "2.814mm"], ["Bs1", "4.71154109036mm"], ["Bs2", "6.9777285790998mm"], ["Rs", "2mm"], - ["FilletType", "1"], ["HalfSlot", "0"], ["VentHoles", "0"], ["HoleDiaIn", "0mm"], - ["HoleDiaOut", "0mm"], - ["HoleLocIn", "0mm"], ["HoleLocOut", "0mm"], ["VentDucts", "0"], ["DuctWidth", "0mm"], - ["DuctPitch", "0mm"], - ["SegAngle", "0deg"], ["LenRegion", "Model_Length"], ["InfoCore", "0"]] - -stator_id = mod2D.create_udp(dll="RMxprt/VentSlotCore.dll", parameters=udp_par_list_stator, library='syslib', - name='my_stator') # name not taken - -########################################################## -# Assign properties to stator -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign properties to the stator. The following code assigns -# the material, name, color, and ``solve_inside`` properties. - -M2D.assign_material(assignment=stator_id, material="30DH_20C_smooth") -stator_id.name = "Stator" -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 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 -# function ``find_elements(lst1, lst2)`` to find the elements in list ``lst1`` with indexes -# in list ``lst2``. - -def find_elements(lst1, lst2): - return [lst1[i] for i in lst2] - - -##################################################################################### -# 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``. - -def find_n_largest(input_len_list, n_largest_edges): - tmp = list(input_len_list) - copied = list(input_len_list) - copied.sort() # sort list so that largest elements are on the far right - index_list = [] - for n in range(1, n_largest_edges + 1): # get index of the nth largest element - index_list.append(tmp.index(copied[-n])) - 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 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 - edge_len_list = list( - map(mod2D.get_edge_length, pm_edges)) # apply method get_edge_length to all elements of list pm_edges - index_2_longest = find_n_largest(edge_len_list, 2) # find the 2 longest edges of the PM - longest_edge_list = find_elements(pm_edges, index_2_longest) - edge_center_list = list(map(mod2D.get_edge_midpoint, - longest_edge_list)) # apply method get_edge_midpoint to all elements of list longest_edge_list - - rad = lambda x: mysqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) - index_largest_r = find_n_largest(list(map(rad, edge_center_list)), 2) - longest_edge_list2 = [longest_edge_list[i] for i in index_largest_r] # reorder: outer first element of the list - if point_direction == 'outer': - my_axis_pos = longest_edge_list2[0] - elif point_direction == 'inner': - my_axis_pos = longest_edge_list2[1] - - mod2D.create_face_coordinate_system(face=pm_face_id, origin=pm_face_id, axis_position=my_axis_pos, - axis="X", name=cs_name) - pm_id.part_coordinate_system = cs_name - mod2D.set_working_coordinate_system('Global') - - -##################################################################################### -# 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], - [55.05576774, 1.098662669, 0]] -OM1_points = [[54.37758185, 22.52393189, 0], [59.69688156, 9.68200639, 0], [63.26490432, 11.15992981, 0], - [57.94560461, 24.00185531, 0]] -IPM1_id = mod2D.create_polyline(points=IM1_points, cover_surface=True, name="PM_I1", - material="Arnold_Magnetics_N30UH_80C_new") -IPM1_id.color = (0, 128, 64) -OPM1_id = mod2D.create_polyline(points=OM1_points, cover_surface=True, name="PM_O1", - material="Arnold_Magnetics_N30UH_80C_new") -OPM1_id.color = (0, 128, 64) - -##################################################################################### -# 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 the PMs along with the local coordinate system. - -mod2D.duplicate_and_mirror([IPM1_id, OPM1_id], origin=[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 the coils. - -coil_id = mod2D.create_rectangle(origin=['DiaRotorLam/2+Airgap+Coil_SetBack', '-Coil_Edge_Short/2', 0], - sizes=['Coil_Edge_Long', 'Coil_Edge_Short', 0], - name='Coil', material="Copper (Annealed)_65C") -coil_id.color = (255, 128, 0) -M2D.modeler.rotate(assignment=coil_id, axis="Z", angle="360deg/SlotNumber/2") -coil_id.duplicate_around_axis(axis="Z", angle="360deg/SlotNumber", nclones='CoilPitch+1', - create_new_objects=True) -id_coils = mod2D.get_objects_w_string("Coil", case_sensitive=True) - -########################################################## -# Create shaft and region -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Create the shaft and region. - -region_id = mod2D.create_circle(position=[0, 0, 0], radius='DiaOuter/2', - num_sides='SegAngle', is_covered=True, name='Region') -shaft_id = mod2D.create_circle(position=[0, 0, 0], radius='DiaShaft/2', - num_sides='SegAngle', is_covered=True, name='Shaft') - -########################################################## -# 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', - num_sides='mapping_angle', is_covered=True, name='Inner_Band') -bandMID_id = mod2D.create_circle(position=[0, 0, 0], radius='(DiaGap - (1.0 * Airgap))/2', - num_sides='mapping_angle', is_covered=True, name='Band') -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 a motion setup to a ``Band`` object named ``RotatingBand_mid``. - -M2D.assign_rotate_motion(assignment='Band', coordinate_system="Global", axis="Z", positive_movement=True, - start_position="InitialPositionMD", angular_velocity="MachineRPM") - -########################################################## -# 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 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", material="30DH_20C_smooth") -rotor_id.color = (0, 128, 255) -mod2D.subtract(rotor_id, shaft_id, keep_originals=True) -void_small_1_id = mod2D.create_circle(position=[62, 0, 0], radius="2.55mm", - num_sides=0, name="void1", material="vacuum") -M2D.modeler.duplicate_around_axis(void_small_1_id, axis="Z", angle="360deg/SymmetryFactor", - clones=2, create_new_objects=False) -void_big_1_id = mod2D.create_circle(position=[29.5643, 12.234389332712, 0], radius='9.88mm/2', - num_sides=0, name="void_big", material="vacuum") -mod2D.subtract(rotor_id, [void_small_1_id, void_big_1_id], keep_originals=False) - -slot_IM1_points = [[37.5302872, 15.54555396, 0], [55.05576774, 1.098662669, 0], [57.33637589, 1.25, 0], - [57.28982158, 2.626565019, 0], [40.25081875, 16.67243502, 0]] -slot_OM1_points = [[54.37758185, 22.52393189, 0], [59.69688156, 9.68200639, 0], [63.53825619, 10.5, 0], - [57.94560461, 24.00185531, 0]] -slot_IM_id = mod2D.create_polyline(points=slot_IM1_points, cover_surface=True, name="slot_IM1", material="vacuum") -slot_OM_id = mod2D.create_polyline(points=slot_OM1_points, cover_surface=True, name="slot_OM1", material="vacuum") - -M2D.modeler.duplicate_and_mirror(assignment=[slot_IM_id, slot_OM_id], origin=[0, 0, 0], - vector=["cos((360deg/SymmetryFactor/2)+90deg)", - "sin((360deg/SymmetryFactor/2)+90deg)", 0]) - -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 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", - name="Section", - mode="axis", - x_pointing=["cos(360deg/SymmetryFactor)", "sin(360deg/SymmetryFactor)", 0], - y_pointing=["-sin(360deg/SymmetryFactor)", "cos(360deg/SymmetryFactor)", 0]) - -mod2D.set_working_coordinate_system("Section") -mod2D.split(object_list, "ZX", sides="NegativeOnly") -mod2D.set_working_coordinate_system("Global") -mod2D.split(object_list, "ZX", sides="PositiveOnly") - -########################################################## -# 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. - -pos_1 = "((DiaGap - (1.0 * Airgap))/4)" -id_bc_1 = mod2D.get_edgeid_from_position(position=[pos_1, 0, 0], assignment='Region') -id_bc_2 = mod2D.get_edgeid_from_position( - position=[pos_1 + "*cos((360deg/SymmetryFactor))", pos_1 + "*sin((360deg/SymmetryFactor))", 0], assignment='Region') -M2D.assign_master_slave(independent=id_bc_1, dependent=id_bc_2, reverse_master=False, reverse_slave=True, - same_as_master=False, boundary="Matching") - -########################################################## -# Assign vector potential -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Assign a vector potential of ``0`` to the second position. - -pos_2 = "(DiaOuter/2)" -id_bc_az = mod2D.get_edgeid_from_position( - position=[pos_2 + "*cos((360deg/SymmetryFactor/2))", pos_2 + "*sin((360deg/SymmetryFactor)/2)", 0], - assignment='Region') -M2D.assign_vector_potential(id_bc_az, vector_value=0, boundary="VectorPotentialZero") - -########################################################## -# 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. - -M2D.assign_coil(assignment=["Coil"], conductors_number=6, polarity="Positive", name="CT_Ph1_P2_C1_Go") -M2D.assign_coil(assignment=["Coil_5"], conductors_number=6, polarity="Negative", name="CT_Ph1_P2_C1_Ret") -M2D.assign_winding(assignment=None, winding_type="Current", is_solid=False, current=PhA_current, parallel_branches=1, - name="Phase_A") -M2D.add_winding_coils(assignment="Phase_A", coils=["CT_Ph1_P2_C1_Go", "CT_Ph1_P2_C1_Ret"]) - -########################################################## -# Define windings in phase B -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define windings in phase B. - -M2D.assign_coil(assignment="Coil_3", conductors_number=6, polarity="Positive", name="CT_Ph3_P1_C2_Go") -M2D.assign_coil(assignment="Coil_4", conductors_number=6, polarity="Positive", name="CT_Ph3_P1_C1_Go") -M2D.assign_winding(assignment=None, winding_type="Current", is_solid=False, current=PhB_current, parallel_branches=1, - name="Phase_B") -M2D.add_winding_coils(assignment="Phase_B", coils=["CT_Ph3_P1_C2_Go", "CT_Ph3_P1_C1_Go"]) - -########################################################## -# Define windings in phase C -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define windings in phase C. - -M2D.assign_coil(assignment="Coil_1", conductors_number=6, polarity="Negative", name="CT_Ph2_P2_C2_Ret") -M2D.assign_coil(assignment="Coil_2", conductors_number=6, polarity="Negative", name="CT_Ph2_P2_C1_Ret") -M2D.assign_winding(assignment=None, winding_type="Current", is_solid=False, current=PhC_current, parallel_branches=1, - name="Phase_C") -M2D.add_winding_coils(assignment="Phase_C", coils=["CT_Ph2_P2_C2_Ret", "CT_Ph2_P2_C1_Ret"]) - -########################################################## -# 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 the mesh operations. - -M2D.mesh.assign_length_mesh(id_coils, inside_selection=True, maximum_length=3, maximum_elements=None, name="coils") -M2D.mesh.assign_length_mesh(stator_id, inside_selection=True, maximum_length=3, maximum_elements=None, name="stator") -M2D.mesh.assign_length_mesh(rotor_id, inside_selection=True, maximum_length=3, maximum_elements=None, name="rotor") - -########################################################## -# 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. - -core_loss_list = ['Rotor', 'Stator'] -M2D.set_core_losses(core_loss_list) - -########################################################## -# Compute transient inductance -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Compute the transient inductance. - -M2D.change_inductance_computation(compute_transient_inductance=True, incremental_matrix=False) - -########################################################## -# Set model depth -# ~~~~~~~~~~~~~~~ -# Set the model depth. - -M2D.model_depth = "Magnetic_Axial_Length" - -########################################################## -# Set symmetry factor -# ~~~~~~~~~~~~~~~~~~~ -# Set the symmetry factor. - -M2D.change_symmetry_multiplier("SymmetryFactor") - -########################################################## -# Create setup and validate -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create the setup and validate it. - -setup = M2D.create_setup(name=setup_name) -setup.props["StopTime"] = "StopTime" -setup.props["TimeStep"] = "TimeStep" -setup.props["SaveFieldsType"] = "None" -setup.props["OutputPerObjectCoreLoss"] = True -setup.props["OutputPerObjectSolidLoss"] = True -setup.props["OutputError"] = True -setup.update() -M2D.validate_simple() - -model = M2D.plot(show=False) -model.plot(os.path.join(M2D.working_directory, "Image.jpg")) - -################################################################################# -# Initialize definitions for output variables -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize the definitions for the output variables. -# These will be used later to generate reports. - -output_vars = { - "Current_A": "InputCurrent(Phase_A)", - "Current_B": "InputCurrent(Phase_B)", - "Current_C": "InputCurrent(Phase_C)", - "Flux_A": "FluxLinkage(Phase_A)", - "Flux_B": "FluxLinkage(Phase_B)", - "Flux_C": "FluxLinkage(Phase_C)", - "pos": "(Moving1.Position -InitialPositionMD) *NumPoles/2", - "cos0": "cos(pos)", - "cos1": "cos(pos-2*PI/3)", - "cos2": "cos(pos-4*PI/3)", - "sin0": "sin(pos)", - "sin1": "sin(pos-2*PI/3)", - "sin2": "sin(pos-4*PI/3)", - "Flux_d": "2/3*(Flux_A*cos0+Flux_B*cos1+Flux_C*cos2)", - "Flux_q": "-2/3*(Flux_A*sin0+Flux_B*sin1+Flux_C*sin2)", - "I_d": "2/3*(Current_A*cos0 + Current_B*cos1 + Current_C*cos2)", - "I_q": "-2/3*(Current_A*sin0 + Current_B*sin1 + Current_C*sin2)", - "Irms": "sqrt(I_d^2+I_q^2)/sqrt(2)", - "ArmatureOhmicLoss_DC": "Irms^2*R_phase", - "Lad": "L(Phase_A,Phase_A)*cos0 + L(Phase_A,Phase_B)*cos1 + L(Phase_A,Phase_C)*cos2", - "Laq": "L(Phase_A,Phase_A)*sin0 + L(Phase_A,Phase_B)*sin1 + L(Phase_A,Phase_C)*sin2", - "Lbd": "L(Phase_B,Phase_A)*cos0 + L(Phase_B,Phase_B)*cos1 + L(Phase_B,Phase_C)*cos2", - "Lbq": "L(Phase_B,Phase_A)*sin0 + L(Phase_B,Phase_B)*sin1 + L(Phase_B,Phase_C)*sin2", - "Lcd": "L(Phase_C,Phase_A)*cos0 + L(Phase_C,Phase_B)*cos1 + L(Phase_C,Phase_C)*cos2", - "Lcq": "L(Phase_C,Phase_A)*sin0 + L(Phase_C,Phase_B)*sin1 + L(Phase_C,Phase_C)*sin2", - "L_d": "(Lad*cos0 + Lbd*cos1 + Lcd*cos2) * 2/3", - "L_q": "(Laq*sin0 + Lbq*sin1 + Lcq*sin2) * 2/3", - "OutputPower": "Moving1.Speed*Moving1.Torque", - "Ui_A": "InducedVoltage(Phase_A)", - "Ui_B": "InducedVoltage(Phase_B)", - "Ui_C": "InducedVoltage(Phase_C)", - "Ui_d": "2/3*(Ui_A*cos0 + Ui_B*cos1 + Ui_C*cos2)", - "Ui_q": "-2/3*(Ui_A*sin0 + Ui_B*sin1 + Ui_C*sin2)", - "U_A": "Ui_A+R_Phase*Current_A", - "U_B": "Ui_B+R_Phase*Current_B", - "U_C": "Ui_C+R_Phase*Current_C", - "U_d": "2/3*(U_A*cos0 + U_B*cos1 + U_C*cos2)", - "U_q": "-2/3*(U_A*sin0 + U_B*sin1 + U_C*sin2)" -} - -########################################################## -# 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 the definition for postprocessing plots. - -post_params = { - "Moving1.Torque": "TorquePlots" -} -################################################################################# -# Initialize definition for postprocessing multiplots -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize the definition for postprocessing multiplots. - -post_params_multiplot = { # reports - ("U_A", "U_B", "U_C", "Ui_A", "Ui_B", "Ui_C"): "PhaseVoltages", - ("CoreLoss", "SolidLoss", "ArmatureOhmicLoss_DC"): "Losses", - ("InputCurrent(Phase_A)", "InputCurrent(Phase_B)", "InputCurrent(Phase_C)"): "PhaseCurrents", - ("FluxLinkage(Phase_A)", "FluxLinkage(Phase_B)", "FluxLinkage(Phase_C)"): "PhaseFluxes", - ("I_d", "I_q"): "Currents_dq", - ("Flux_d", "Flux_q"): "Fluxes_dq", - ("Ui_d", "Ui_q"): "InducedVoltages_dq", - ("U_d", "U_q"): "Voltages_dq", - ("L(Phase_A,Phase_A)", "L(Phase_B,Phase_B)", "L(Phase_C,Phase_C)", "L(Phase_A,Phase_B)", "L(Phase_A,Phase_C)", - "L(Phase_B,Phase_C)"): "PhaseInductances", - ("L_d", "L_q"): "Inductances_dq", - ("CoreLoss", "CoreLoss(Stator)", "CoreLoss(Rotor)"): "CoreLosses", - ("EddyCurrentLoss", "EddyCurrentLoss(Stator)", "EddyCurrentLoss(Rotor)"): "EddyCurrentLosses (Core)", - ("ExcessLoss", "ExcessLoss(Stator)", "ExcessLoss(Rotor)"): "ExcessLosses (Core)", - ("HysteresisLoss", "HysteresisLoss(Stator)", "HysteresisLoss(Rotor)"): "HysteresisLosses (Core)", - ("SolidLoss", "SolidLoss(IPM1)", "SolidLoss(IPM1_1)", "SolidLoss(OPM1)", "SolidLoss(OPM1_1)"): "SolidLoss" -} - -########################################################## -# Create report -# ~~~~~~~~~~~~~ -# Create a report. - -for k, v in post_params.items(): - M2D.post.create_report(expressions=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, - plot_name=v) - -########################################################## -# 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 the project. - -M2D.save_project() -M2D.analyze_setup(setup_name, use_auto_settings=False) - -########################################################## -# 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. - -faces_reg = mod2D.get_object_faces(object_list[1].name) # Region -plot1 = M2D.post.create_fieldplot_surface(assignment=faces_reg, quantity='Flux_Lines', intrinsics={ - "Time": M2D.variable_manager.variables["StopTime"].evaluated_value}, plot_name="Flux_Lines") - -########################################################## -# 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 a simulation result from a solved setup and cast it in a ``SolutionData`` object. -# Plot the desired expression by using Matplotlib plot(). - -solutions = M2D.post.get_solution_data(expressions="Moving1.Torque", - primary_sweep_variable="Time") -#solutions.plot() - -############################################### -# 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 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. - -M2D.release_desktop() diff --git a/examples/03-Maxwell/Maxwell2D_Transformer_LL.py b/examples/03-Maxwell/Maxwell2D_Transformer_LL.py deleted file mode 100644 index 6817586e7eb..00000000000 --- a/examples/03-Maxwell/Maxwell2D_Transformer_LL.py +++ /dev/null @@ -1,274 +0,0 @@ -""" -Transformer leakage inductance calculation in Maxwell 2D Magnetostatic ----------------------------------------------------------------------- -This example shows how you can use pyAEDT to create a Maxwell 2D -magnetostatic analysis to calculate transformer leakage -inductance and reactance. -The analysis based on this document form page 8 on: -https://www.ee.iitb.ac.in/~fclab/FEM/FEM1.pdf -""" - -########################################################## -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ - -import tempfile -from ansys.aedt.core import Maxwell2d - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -################################## -# Initialize and launch Maxwell 2D -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize and launch Maxwell 2D, providing the version, path to the project, and the design -# name and type. - -non_graphical = False - -project_name = "Transformer_leakage_inductance" -design_name = "1 Magnetostatic" -solver = "MagnetostaticXY" -desktop_version = "2024.2" - -m2d = Maxwell2d(version=desktop_version, - new_desktop=False, - design=design_name, - project=project_name, - solution_type=solver, - non_graphical=non_graphical) - -######################### -# Initialize dictionaries -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize dictionaries that contain all the definitions for the design variables. - -mod = m2d.modeler -mod.model_units = "mm" - -dimensions = { - "core_width": "1097mm", - "core_height": "2880mm", - "core_opening_x1": "270mm", - "core_opening_x2": "557mm", - "core_opening_y1": "540mm", - "core_opening_y2": "2340mm", - "core_opening_width": "core_opening_x2-core_opening_x1", - "core_opening_height": "core_opening_y2-core_opening_y1", - "LV_x1": "293mm", - "LV_x2": "345mm", - "LV_width": "LV_x2-LV_x1", - "LV_mean_radius": "LV_x1+LV_width/2", - "LV_mean_turn_length": "pi*2*LV_mean_radius", - "LV_y1": "620mm", - "LV_y2": "2140mm", - "LV_height": "LV_y2-LV_y1", - "HV_x1": "394mm", - "HV_x2": "459mm", - "HV_width": "HV_x2-HV_x1", - "HV_mean_radius": "HV_x1+HV_width/2", - "HV_mean_turn_length": "pi*2*HV_mean_radius", - "HV_y1": "620mm", - "HV_y2": "2140mm", - "HV_height": "HV_y2-HV_y1", - "HV_LV_gap_radius": "(LV_x2 + HV_x1)/2", - "HV_LV_gap_length": "pi*2*HV_LV_gap_radius", -} - -specifications = { - "Amp_turns": "135024A", - "Frequency": "50Hz", - "HV_turns": "980", - "HV_current": "Amp_turns/HV_turns", -} - -#################################### -# Define variables from dictionaries -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define design variables from the created dictionaries. - -m2d.variable_manager.set_variable(name="Dimensions") - -for k, v in dimensions.items(): - m2d[k] = v - -m2d.variable_manager.set_variable(name="Windings") - -for k, v in specifications.items(): - m2d[k] = v - -########################## -# Create design geometries -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create transformer core, HV and LV windings, and the region. - -core_id = mod.create_rectangle( - position=[0, 0, 0], - dimension_list=["core_width", "core_height", 0], - name="core", - matname="steel_1008", -) - -core_hole_id = mod.create_rectangle( - position=["core_opening_x1", "core_opening_y1", 0], - dimension_list=["core_opening_width", "core_opening_height", 0], - name="core_hole", -) - -mod.subtract(blank_list=[core_id], tool_list=[core_hole_id], keep_originals=False) - -lv_id = mod.create_rectangle( - position=["LV_x1", "LV_y1", 0], - dimension_list=["LV_width", "LV_height", 0], - name="LV", - matname="copper", -) - -hv_id = mod.create_rectangle( - position=["HV_x1", "HV_y1", 0], - dimension_list=["HV_width", "HV_height", 0], - name="HV", - matname="copper", -) - -# Very small region is enough, because all the flux is concentrated in the core -region_id = mod.create_region( - pad_percent=[20, 10, 0, 10] -) - -########################### -# Assign boundary condition -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign vector potential to zero on all region boundaries. This makes x=0 edge a symmetry boundary. - -region_edges = region_id.edges - -m2d.assign_vector_potential( - input_edge=region_edges, - bound_name="VectorPotential1" -) - -############################## -# Create initial mesh settings -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Assign a relatively dense mesh to all objects to ensure that the energy is calculated accurately. - -m2d.mesh.assign_length_mesh( - names=["core", "Region", "LV", "HV"], - maxlength=50, - maxel=None, - meshop_name="all_objects" -) - -#################### -# Define excitations -# ~~~~~~~~~~~~~~~~~~ -# Assign the same current in amp-turns but in opposite directions to HV and LV windings. - -m2d.assign_current( - object_list=lv_id, - amplitude="Amp_turns", - name="LV" -) -m2d.assign_current( - object_list=hv_id, - amplitude="Amp_turns", - name="HV", - swap_direction=True -) - -############################## -# Create and analyze the setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create and analyze the setup. Setu no. of minimum passes to 3 to ensure accuracy. - -m2d.create_setup( - setupname="Setup1", - MinimumPasses=3 -) -m2d.analyze_setup() - - -######################################################## -# Calculate transformer leakage inductance and reactance -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Calculate transformer leakage inductance from the magnetic energy. - -field_calculator = m2d.ofieldsreporter - -field_calculator.EnterQty("Energy") -field_calculator.EnterSurf("HV") -field_calculator.CalcOp("Integrate") -field_calculator.EnterScalarFunc("HV_mean_turn_length") -field_calculator.CalcOp("*") - -field_calculator.EnterQty("Energy") -field_calculator.EnterSurf("LV") -field_calculator.CalcOp("Integrate") -field_calculator.EnterScalarFunc("LV_mean_turn_length") -field_calculator.CalcOp("*") - -field_calculator.EnterQty("Energy") -field_calculator.EnterSurf("Region") -field_calculator.CalcOp("Integrate") -field_calculator.EnterScalarFunc("HV_LV_gap_length") -field_calculator.CalcOp("*") - -field_calculator.CalcOp("+") -field_calculator.CalcOp("+") - -field_calculator.EnterScalar(2) -field_calculator.CalcOp("*") -field_calculator.EnterScalarFunc("HV_current") -field_calculator.EnterScalarFunc("HV_current") -field_calculator.CalcOp("*") -field_calculator.CalcOp("/") -field_calculator.AddNamedExpression("Leakage_inductance", "Fields") - -field_calculator.CopyNamedExprToStack("Leakage_inductance") -field_calculator.EnterScalar(2) -field_calculator.EnterScalar(3.14159265358979) -field_calculator.EnterScalarFunc("Frequency") -field_calculator.CalcOp("*") -field_calculator.CalcOp("*") -field_calculator.CalcOp("*") -field_calculator.AddNamedExpression("Leakage_reactance", "Fields") - -m2d.post.create_report( - expressions=["Leakage_inductance", "Leakage_reactance"], - report_category="Fields", - primary_sweep_variable="core_width", - plot_type="Data Table", - plotname="Transformer Leakage Inductance", -) - -###################################################################### -# Print leakage inductance and reactance values in the Message Manager -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Print leakage inductance and reactance values in the Message Manager - -m2d.logger.clear_messages() -m2d.logger.info( - "Leakage_inductance = {:.4f}H".format(m2d.post.get_scalar_field_value(quantity_name="Leakage_inductance")) -) -m2d.logger.info( - "Leakage_reactance = {:.2f}Ohm".format(m2d.post.get_scalar_field_value(quantity_name="Leakage_reactance")) -) - -###################################### -# Plot energy in the simulation domain -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Most of the energy is confined in the air between the HV and LV windings. - -object_faces = [] -for name in mod.object_names: - object_faces.extend(m2d.modeler.get_object_faces(name)) - -energy_field_overlay = m2d.post.create_fieldplot_surface( - objlist=object_faces, - quantityName="energy", - plot_name="Energy", -) - -m2d.save_project() -m2d.release_desktop() -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell2D_Transient.py b/examples/03-Maxwell/Maxwell2D_Transient.py deleted file mode 100644 index db0f2f7bd68..00000000000 --- a/examples/03-Maxwell/Maxwell2D_Transient.py +++ /dev/null @@ -1,157 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import os -import ansys.aedt.core -import tempfile - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -############################################################################### -# 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 a Maxwell 2D design and save the project. - -maxwell_2d = ansys.aedt.core.Maxwell2d(solution_type="TransientXY", version=aedt_version, non_graphical=non_graphical, - new_desktop=True, project=ansys.aedt.core.generate_unique_project_name()) - -############################################################################### -# Create rectangle and duplicate it -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a rectangle and duplicate it. - -rect1 = maxwell_2d.modeler.create_rectangle([0, 0, 0], [10, 20], name="winding", material="copper") -added = rect1.duplicate_along_line([14, 0, 0]) -rect2 = maxwell_2d.modeler[added[0]] - -############################################################################### -# Create air region -# ~~~~~~~~~~~~~~~~~ -# Create an air region. - -region = maxwell_2d.modeler.create_region([100, 100, 100, 100]) - -############################################################################### -# 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 the model. - -maxwell_2d.plot(show=False, output_file=os.path.join(temp_dir.name, "Image.jpg"), plot_air_objects=True) - -############################################################################### -# Create setup -# ~~~~~~~~~~~~ -# Create the transient setup. - -setup = maxwell_2d.create_setup() -setup.props["StopTime"] = "0.02s" -setup.props["TimeStep"] = "0.0002s" -setup.props["SaveFieldsType"] = "Every N Steps" -setup.props["N Steps"] = "1" -setup.props["Steps From"] = "0s" -setup.props["Steps To"] = "0.002s" - -############################################################################### -# Create rectangular plot -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Create a rectangular plot. - -maxwell_2d.post.create_report("InputCurrent(PHA)", domain="Time", primary_sweep_variable="Time", - plot_name="Winding Plot 1") - -############################################################################### -# Solve model -# ~~~~~~~~~~~ -# Solve the model. - -maxwell_2d.analyze(use_auto_settings=False) - -############################################################################### -# 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 -timesteps = [str(i * 2e-4) + "s" for i in range(11)] -id_list = [f.id for f in face_lists] - -gif = maxwell_2d.post.plot_animated_field(quantity="Mag_B", assignment=id_list, plot_type="Surface", - intrinsics={"Time": "0s"}, variation_variable="Time", - variations=timesteps, show=False, export_gif=False) -gif.isometric_view = False -gif.camera_position = [15, 15, 80] -gif.focal_point = [15, 15, 0] -gif.roll_angle = 0 -gif.elevation_angle = 0 -gif.azimuth_angle = 0 -# Set off_screen to False to visualize the animation. -# gif.off_screen = False -gif.animate() - -############################################################################### -# Generate plot outside 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. - -maxwell_2d.release_desktop() -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell3DTeam7.py b/examples/03-Maxwell/Maxwell3DTeam7.py deleted file mode 100644 index 14e8fe3a139..00000000000 --- a/examples/03-Maxwell/Maxwell3DTeam7.py +++ /dev/null @@ -1,429 +0,0 @@ -""" -Maxwell 3D: asymmetric conductor analysis ------------------------------------------ -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. -https://www.compumag.org/wp/wp-content/uploads/2018/06/problem7.pdf -""" -########################################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import numpy as np -import os -import tempfile - -from ansys.aedt.core import Maxwell3d -from ansys.aedt.core.generic.general_methods import write_csv - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -########################################################################################### -# 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. 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" - -m3d = Maxwell3d( - project=project_name, - design=design_name, - solution_type=solver, - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True -) -m3d.modeler.model_units = "mm" - -########################################################################################### -# 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 - -setup = m3d.create_setup(name="Setup1") -setup.props["Frequency"] = "200Hz" -setup.props["HasSweepSetup"] = True -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 -setup.update() - -########################################################################################### -# Define coil dimensions -# ~~~~~~~~~~~~~~~~~~~~~~ -# Define coil dimensions as shown on the TEAM7 drawing of the coil. - -coil_external = 150 + 25 + 25 -coil_internal = 150 -coil_r1 = 25 -coil_r2 = 50 -coil_thk = coil_r2 - coil_r1 -coil_height = 100 -coil_centre = [294 - 25 - 150 / 2, 25 + 150 / 2, 19 + 30 + 100 / 2] - -# Use expressions to construct the three dimensions needed to describe the midpoints of -# the coil. - -dim1 = coil_internal / 2 + (coil_external - coil_internal) / 4 -dim2 = coil_internal / 2 - coil_r1 -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 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 a polyline. One quarter of the coil is modeled by sweeping a 2D sheet along a polyline. - -test = m3d.modeler.create_polyline(points=[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 unit the polyline to create a full coil. - -m3d.modeler.duplicate_around_axis( - "Coil", axis="Global", angle=90, clones=4, create_new_objects=True, is_3d_comp=False -) -m3d.modeler.unite("Coil, Coil_1, Coil_2") -m3d.modeler.unite("Coil, Coil_3") -m3d.modeler.fit_all() - -########################################################################################### -# 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 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 a design variable for coil excitation. The NB units here are AmpereTurns. - -Coil_Excitation = 2742 -m3d["Coil_Excitation"] = str(Coil_Excitation) + "A" -m3d.assign_current(assignment="Coil_Section1", amplitude="Coil_Excitation", solid=False) -m3d.modeler.set_working_coordinate_system("Global") - -########################################################################################### -# 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 the aluminium plate with a hole by subtracting two rectangular cuboids. - -plate = m3d.modeler.create_box(origin=[0, 0, 0], sizes=[294, 294, 19], name="Plate", material="team7_aluminium") -m3d.modeler.fit_all() -m3d.modeler.create_box(origin=[18, 18, 0], sizes=[108, 108, 19], name="Hole") -m3d.modeler.subtract(blank_list="Plate", tool_list=["Hole"], keep_originals=False) - -########################################################################################### -# 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 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. - -m3d.eddy_effects_on(assignment="Plate") -m3d.eddy_effects_on(assignment=["Coil", "Region", "Line_A1_B1mesh", "Line_A2_B2mesh"], enable_eddy_effects=False, - enable_displacement_current=False) - -################################################################################ -# 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.ofieldsreporter -Fields.CalcStack("clear") -Fields.EnterQty("B") -Fields.CalcOp("ScalarZ") -Fields.EnterScalarFunc("Phase") -Fields.CalcOp("AtPhase") -Fields.EnterScalar(10000) -Fields.CalcOp("*") -Fields.CalcOp("Smooth") -Fields.AddNamedExpression("Bz", "Fields") - -################################################################################ -# 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" - -line_points_1 = [["0mm", "72mm", "34mm"], ["288mm", "72mm", "34mm"]] -polyline = m3d.modeler.create_polyline(points=line_points_1, name=lines[0]) -l1_mesh = m3d.modeler.create_polyline(points=line_points_1, name=lines[0] + "mesh") -l1_mesh.set_crosssection_properties(type="Circle", width=mesh_diameter) - -line_points_2 = [["0mm", "144mm", "34mm"], ["288mm", "144mm", "34mm"]] -polyline2 = m3d.modeler.create_polyline(points=line_points_2, name=lines[1]) -l2_mesh = m3d.modeler.create_polyline(points=line_points_2, name=lines[1] + "mesh") -l2_mesh.set_crosssection_properties(type="Circle", width=mesh_diameter) - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -m3d.plot(show=False, output_file=os.path.join(temp_dir.name, "model.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. - -dataset = [ - "Bz A1_B1 000 0", - "Bz A1_B1 050 0", - "Bz A1_B1 050 90", - "Bz A1_B1 200 0", - "Bz A1_B1 200 90", - "Bz A2_B2 050 0", - "Bz A2_B2 050 90", - "Bz A2_B2 200 0", - "Bz A2_B2 200 90", -] -header = ["Distance [mm]", "Bz [Tesla]"] - -line_length = [0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198, 216, 234, 252, 270, 288] -data = [ - [ - -6.667, - -7.764, - -8.707, - -8.812, - -5.870, - 8.713, - 50.40, - 88.47, - 100.9, - 104.0, - 104.8, - 104.9, - 104.6, - 103.1, - 97.32, - 75.19, - 29.04, - ], - [ - 4.90, - -17.88, - -22.13, - -20.19, - -15.67, - 0.36, - 43.64, - 78.11, - 71.55, - 60.44, - 53.91, - 52.62, - 53.81, - 56.91, - 59.24, - 52.78, - 27.61, - ], - [-1.16, 2.84, 4.15, 4.00, 3.07, 2.31, 1.89, 4.97, 12.61, 14.15, 13.04, 12.40, 12.05, 12.27, 12.66, 9.96, 2.36], - [ - -3.63, - -18.46, - -23.62, - -21.59, - -16.09, - 0.23, - 44.35, - 75.53, - 63.42, - 53.20, - 48.66, - 47.31, - 48.31, - 51.26, - 53.61, - 46.11, - 24.96, - ], - [-1.38, 1.20, 2.15, 1.63, 1.10, 0.27, -2.28, -1.40, 4.17, 3.94, 4.86, 4.09, 3.69, 4.60, 3.48, 4.10, 0.98], - [ - -1.83, - -8.50, - -13.60, - -15.21, - -14.48, - -5.62, - 28.77, - 60.34, - 61.84, - 56.64, - 53.40, - 52.36, - 53.93, - 56.82, - 59.48, - 52.08, - 26.56, - ], - [-1.63, -0.60, -0.43, 0.11, 1.26, 3.40, 6.53, 10.25, 11.83, 11.83, 11.01, 10.58, 10.80, 10.54, 10.62, 9.03, 1.79], - [ - -0.86, - -7.00, - -11.58, - -13.36, - -13.77, - -6.74, - 24.63, - 53.19, - 54.89, - 50.72, - 48.03, - 47.13, - 48.25, - 51.35, - 53.35, - 45.37, - 24.01, - ], - [-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], -] - -################################################################################ -# Write dataset values in a CSV file -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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. - -line_length.insert(0, header[0]) -for i in range(len(dataset)): - data[i].insert(0, header[1]) - ziplist = zip(line_length, data[i]) - file_path = os.path.join(temp_dir.name, str(dataset[i]) + ".csv") - write_csv(output_file=file_path, list_data=ziplist) - -################################################################################ -# Create rectangular plots and import test data into report -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create rectangular plots, using text file encoding to control their formatting. -# Import test data into correct plot and overlay with simulation results. -# Variations for a DC plot must have different frequency and phase than the other plots. - -for item in range(len(dataset)): - if item % 2 == 0: - t = dataset[item] - plot_name = t[0:3] + "Along the Line" + t[2:9] + ", " + t[9:12] + "Hz" - if t[9:12] == "000": - variations = { - "Distance": ["All"], - "Freq": [str(dc_freq) + "Hz"], - "Phase": ["0deg"], - "Coil_Excitation": ["All"], - } - else: - variations = { - "Distance": ["All"], - "Freq": [t[9:12] + "Hz"], - "Phase": ["0deg", "90deg"], - "Coil_Excitation": ["All"], - } - report = m3d.post.create_report(expressions=t[0:2], variations=variations, primary_sweep_variable="Distance", - report_category="Fields", context="Line_" + t[3:8], plot_name=plot_name) - file_path = os.path.join(temp_dir.name, str(dataset[i]) + ".csv") - report.import_traces(file_path, plot_name) - -################################################################################################### -# Analyze project -# ~~~~~~~~~~~~~~~ -# Analyze the project. - -m3d.analyze() - -################################################################################################### -# 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. - -surf_list = m3d.modeler.get_object_faces("Plate") -intrinsic_dict = {"Freq": "200Hz", "Phase": "0deg"} -m3d.post.create_fieldplot_surface(surf_list, "Mag_J", intrinsics=intrinsic_dict, plot_name="Mag_J") -m3d.post.create_fieldplot_surface(surf_list, "Mag_B", intrinsics=intrinsic_dict, plot_name="Mag_B") -m3d.post.create_fieldplot_surface(surf_list, "Mesh", intrinsics=intrinsic_dict, plot_name="Mesh") - -#################################################################################################### -# Release AEDT and clean up temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Release AEDT and remove both the project and temporary directories. - -m3d.release_desktop(True, True) -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell3D_Choke.py b/examples/03-Maxwell/Maxwell3D_Choke.py deleted file mode 100644 index 4d8c60ed9ab..00000000000 --- a/examples/03-Maxwell/Maxwell3D_Choke.py +++ /dev/null @@ -1,222 +0,0 @@ -""" -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 ansys.aedt.core -import tempfile - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can define ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Launch Maxwell3D -# ~~~~~~~~~~~~~~~~ -# Launch Maxwell 3D 2023 R2 in graphical mode. - -m3d = ansys.aedt.core.Maxwell3d(project=ansys.aedt.core.generate_unique_project_name(), - solution_type="EddyCurrent", - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True - ) - -############################################################################### -# 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 -# ``"Number of Windings"``, ``"Layer"``, and ``"Layer Type"``, that have -# 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 -# one value per dictionary can be ``"True"``. If all values are ``True``, only the first one -# remains set to ``True``. If all values are ``False``, the first value is chosen as the -# correct one by default. For the dictionaries from ``"Core"`` through ``"Inner Winding"``, -# values must be strings, floats, or integers. -# -# Descriptions follow for primary keys: -# -# - ``"Number of Windings"``: Number of windings around the core -# - ``"Layer"``: Number of layers of all windings -# - ``"Layer Type"``: Whether layers of a winding are linked to each other -# - ``"Similar Layer"``: Whether layers of a winding have the same number of turns and same spacing between turns -# - ``"Mode"``: When there are only two windows, whether they are in common or differential mode -# - ``"Wire Section"``: Type of wire section and number of segments -# - ``"Core"``: Design of the core -# - ``"Outer Winding"``: Design of the first layer or outer layer of a winding and the common parameters for all layers -# - ``"Mid Winding"``: Turns and turns spacing ("Coil Pit") for the second or mid layer if it is necessary -# - ``"Inner Winding"``: Turns and turns spacing ("Coil Pit") for the third or inner layer if it is necessary -# - ``"Occupation(%)"``: An informative parameter that is useless to modify -# -# The following parameter values work. You can modify them if you want. - -values = { - "Number of Windings": {"1": False, "2": False, "3": True, "4": False}, - "Layer": {"Simple": False, "Double": False, "Triple": True}, - "Layer Type": {"Separate": False, "Linked": True}, - "Similar Layer": {"Similar": False, "Different": True}, - "Mode": {"Differential": True, "Common": False}, - "Wire Section": {"None": False, "Hexagon": False, "Octagon": True, "Circle": False}, - "Core": { - "Name": "Core", - "Material": "ferrite", - "Inner Radius": 100, - "Outer Radius": 143, - "Height": 25, - "Chamfer": 0.8, - }, - "Outer Winding": { - "Name": "Winding", - "Material": "copper", - "Inner Radius": 100, - "Outer Radius": 143, - "Height": 25, - "Wire Diameter": 5, - "Turns": 2, - "Coil Pit(deg)": 4, - "Occupation(%)": 0, - }, - "Mid Winding": {"Turns": 7, "Coil Pit(deg)": 4, "Occupation(%)": 0}, - "Inner Winding": {"Turns": 10, "Coil Pit(deg)": 4, "Occupation(%)": 0}, -} - -############################################################################### -# 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(temp_dir.name, "choke_example.json") - -with open(json_path, "w") as outfile: - json.dump(values, outfile) - -############################################################################### -# 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: -# -# - Checks if the JSON file is correctly written (as explained in the rules) -# - Checks inequations on windings parameters to avoid having unintended intersections - -dictionary_values = m3d.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 -# argument. - -list_object = m3d.modeler.create_choke(json_path) -print(list_object) -core = list_object[1] -first_winding_list = list_object[2] -second_winding_list = list_object[3] -third_winding_list = list_object[4] - -############################################################################### -# Assign excitations -# ~~~~~~~~~~~~~~~~~~ -# Assign excitations. - -first_winding_faces = m3d.modeler.get_object_faces(first_winding_list[0].name) -second_winding_faces = m3d.modeler.get_object_faces(second_winding_list[0].name) -third_winding_faces = m3d.modeler.get_object_faces(third_winding_list[0].name) -m3d.assign_current([first_winding_faces[-1]], amplitude=1000, phase="0deg", swap_direction=False, name="phase_1_in") -m3d.assign_current([first_winding_faces[-2]], amplitude=1000, phase="0deg", swap_direction=True, name="phase_1_out") -m3d.assign_current([second_winding_faces[-1]], amplitude=1000, phase="120deg", swap_direction=False, name="phase_2_in") -m3d.assign_current([second_winding_faces[-2]], amplitude=1000, phase="120deg", swap_direction=True, name="phase_2_out") -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 the matrix. - -m3d.assign_matrix(["phase_1_in", "phase_2_in", "phase_3_in"], matrix_name="current_matrix") - -############################################################################### -# Create mesh operation -# ~~~~~~~~~~~~~~~~~~~~~ -# Create the mesh operation. - -mesh = m3d.mesh -mesh.assign_skin_depth(assignment=[first_winding_list[0], second_winding_list[0], third_winding_list[0]], - skin_depth=0.20, triangulation_max_length="10mm", name="skin_depth") -mesh.assign_surface_mesh_manual([first_winding_list[0], second_winding_list[0], third_winding_list[0]], - surface_deviation=None, normal_dev="30deg", name="surface_approx") - -############################################################################### -# 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 a setup with a sweep to run the simulation. Depending on your machine's -# computing power, the simulation can take some time to run. - -setup = m3d.create_setup("MySetup") -print(setup.props) -setup.props["Frequency"] = "100kHz" -setup.props["PercentRefinement"] = 15 -setup.props["MaximumPasses"] = 10 -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 the project. - -m3d.save_project() -m3d.modeler.fit_all() -m3d.plot(show=False, output_file=os.path.join(temp_dir.name, "Image.jpg"), plot_air_objects=True) - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.release_desktop` method. -# All methods provide for saving the project before closing. - -m3d.release_desktop() -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell3D_Segmentation.py b/examples/03-Maxwell/Maxwell3D_Segmentation.py deleted file mode 100644 index 5d25a48dfc6..00000000000 --- a/examples/03-Maxwell/Maxwell3D_Segmentation.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -Maxwell 3D: magnet segmentation -------------------------------- -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. - -from ansys.aedt.core import downloads -from ansys.aedt.core import Maxwell3d - -import tempfile - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set local temporary folder to export the .aedt file to. - -aedt_file = downloads.download_file("object_segmentation", "Motor3D_obj_segments.aedt", temp_dir.name) - -################################################################################## -# Launch Maxwell 3D -# ~~~~~~~~~~~~~~~~~ -# Launch Maxwell 3D. - -m3d = Maxwell3d(project=aedt_file, - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical) - -################################################################################## -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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:`ansys.aedt.core.modeler.cad.object_3d.Object3d`. -# ``apply_mesh_sheets`` is enabled which means that the mesh sheets will -# be applied in the geometry too. -# In this specific case we give as input the name of the magnet. - -segments_number = 5 -object_name = "PM_I1" -sheets_1 = modeler.objects_segmentation(object_name, segments=segments_number, apply_mesh_sheets=True) - -################################################################################## -# 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. - -segments_number = 4 -object_name = "PM_I1_1" -magnet_id = [obj.id for obj in modeler.object_list if obj.name == object_name][0] -sheets_2 = modeler.objects_segmentation(magnet_id, segments=segments_number, apply_mesh_sheets=True) - -################################################################################## -# 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:`ansys.aedt.core.modeler.cad.object_3d.Object3d`. - -segmentation_thickness = 1 -object_name = "PM_O1" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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. - -object_name = "PM_O1_1" -segments_number = 10 -sheets_4 = modeler.objects_segmentation(object_name, segments=segments_number) - -################################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Save the project and close AEDT. - -m3d.save_project() -m3d.release_desktop() -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py b/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py deleted file mode 100644 index c70eb5f6881..00000000000 --- a/examples/03-Maxwell/Maxwell3D_Team3_bath_plate.py +++ /dev/null @@ -1,240 +0,0 @@ -""" -Maxwell 3D: bath plate analysis -------------------------------- -This example uses PyAEDT to set up the TEAM 3 bath plate problem and -solve it using the Maxwell 3D Eddy Current solver. -https://www.compumag.org/wp/wp-content/uploads/2018/06/problem3.pdf -""" -################################################################################## -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import os -import ansys.aedt.core -import tempfile - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -################################################################################## -# 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 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 = os.path.join(temp_dir.name, "COMPUMAG.aedt") -design_name = "TEAM 3 Bath Plate" -solver = "EddyCurrent" - -m3d = ansys.aedt.core.Maxwell3d( - project=project_name, - design=design_name, - solution_type=solver, - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True, -) -m3d.modeler.model_units = "mm" - -############################################################################### -# 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) + m3d.modeler.model_units - -################################################################################ -# 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 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 a ladder plate and assign it the newly created material ``team3_aluminium``. - -m3d.modeler.create_box(origin=[-30, -55, 0], sizes=[60, 110, -6.35], name="LadderPlate", material="team3_aluminium") -m3d.modeler.create_box(origin=[-20, -35, 0], sizes=[40, 30, -6.35], name="CutoutTool1") -m3d.modeler.create_box(origin=[-20, 5, 0], sizes=[40, 30, -6.35], name="CutoutTool2") -m3d.modeler.subtract("LadderPlate", ["CutoutTool1", "CutoutTool2"], keep_originals=False) - -################################################################################ -# Add mesh refinement to ladder plate -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Add a mesh refinement to the ladder plate. - -m3d.mesh.assign_length_mesh("LadderPlate", maximum_length=3, maximum_elements=None, name="Ladder_Mesh") - -################################################################################ -# 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. - -m3d.modeler.create_cylinder(orientation="Z", origin=[0, "Coil_Position", 15], radius=40, height=20, name="SearchCoil", - material="copper") -m3d.modeler.create_cylinder(orientation="Z", origin=[0, "Coil_Position", 15], radius=20, height=20, name="Bore", - material="copper") -m3d.modeler.subtract("SearchCoil", "Bore", keep_originals=False) -m3d.modeler.section("SearchCoil", "YZ") -m3d.modeler.separate_bodies("SearchCoil_Section1") -m3d.modeler.delete("SearchCoil_Section1_Separate1") -m3d.assign_current(assignment=["SearchCoil_Section1"], amplitude=1260, solid=False, name="SearchCoil_Excitation") - -################################################################################ -# 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. - -line_points = [["0mm", "-55mm", "0.5mm"], ["0mm", "55mm", "0.5mm"]] -m3d.modeler.create_polyline(points=line_points, name="Line_AB") -poly = m3d.modeler.create_polyline(points=line_points, name="Line_AB_MeshRefinement") -poly.set_crosssection_properties(type="Circle", width="0.5mm") - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -m3d.plot(show=False, output_file=os.path.join(temp_dir.name, "Image.jpg"), plot_air_objects=False) - -############################################################################### -# Add Maxwell 3D setup -# ~~~~~~~~~~~~~~~~~~~~ -# Add a Maxwell 3D setup with frequency points at 50 Hz and 200 Hz. - -setup = m3d.create_setup(name="Setup1") -setup.props["Frequency"] = "200Hz" -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 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(assignment=["LadderPlate"], enable_eddy_effects=True, enable_displacement_current=True) -m3d.eddy_effects_on(assignment=["SearchCoil"], enable_eddy_effects=False, enable_displacement_current=True) - -################################################################################ -# Add linear parametric sweep -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Add a linear parametric sweep for the two coil positions. - -sweep_name = "CoilSweep" -param = m3d.parametrics.add("Coil_Position", -20, 0, 20, "LinearStep", name=sweep_name) -param["SaveFields"] = True -param["CopyMesh"] = False -param["SolveWithCopiedMeshOnly"] = True - -################################################################################ -# Solve parametric sweep -# ~~~~~~~~~~~~~~~~~~~~~~ -# Solve the parametric sweep directly so that results of all variations are available. - -m3d.analyze_setup(sweep_name) - -############################################################################### -# Create expression for Bz -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create an expression for Bz using the fields calculator. - -Fields = m3d.ofieldsreporter -Fields.EnterQty("B") -Fields.CalcOp("ScalarZ") -Fields.EnterScalar(1000) -Fields.CalcOp("*") -Fields.CalcOp("Smooth") -Fields.AddNamedExpression("Bz", "Fields") - -############################################################################### -# 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": ["All"]} -m3d.post.create_report(expressions="mag(Bz)", variations=variations, primary_sweep_variable="Distance", - report_category="Fields", context="Line_AB", plot_name="mag(Bz) Along 'Line_AB' Coil") - -############################################################################### -# Get simulation results from a solved setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Get simulation results from a solved setup as a ``SolutionData`` object. - -solutions = m3d.post.get_solution_data( - expressions="mag(Bz)", - report_category="Fields", - context="Line_AB", - variations=variations, - primary_sweep_variable="Distance", -) - -############################################################################### -# 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 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 the induced current density, ``"Mag_J"``, on the surface of the ladder plate. - -ladder_plate = m3d.modeler.objects_by_name["LadderPlate"] -intrinsic_dict = {"Freq": "50Hz", "Phase": "0deg"} -m3d.post.create_fieldplot_surface(ladder_plate.faces, "Mag_J", intrinsics=intrinsic_dict, plot_name="Mag_J") - -############################################################################### -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT from the script engine, leaving both AEDT and the project open. - -m3d.release_desktop() - -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell_Control_Program.py b/examples/03-Maxwell/Maxwell_Control_Program.py deleted file mode 100644 index 81ed5306ad0..00000000000 --- a/examples/03-Maxwell/Maxwell_Control_Program.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -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 ansys.aedt.core import downloads -from ansys.aedt.core.generic.general_methods import generate_unique_folder_name -from ansys.aedt.core import Maxwell2d - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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. - -m2d = Maxwell2d(project=aedt_file, - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical) - -################################################################################## -# Set active design -# ~~~~~~~~~~~~~~~~~ -# Set active design. - -m2d.set_active_design("1 time step control") - -################################################################################## -# Get design setup -# ~~~~~~~~~~~~~~~~ -# Get design setup to enable the control program to. - -setup = m2d.setups[0] - -################################################################################## -# 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. - -setup.analyze() - - -################################################################################## -# 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 the project and close AEDT. - -m2d.save_project() -m2d.release_desktop() diff --git a/examples/03-Maxwell/Maxwell_Magnet.py b/examples/03-Maxwell/Maxwell_Magnet.py deleted file mode 100644 index c4e5aa68756..00000000000 --- a/examples/03-Maxwell/Maxwell_Magnet.py +++ /dev/null @@ -1,138 +0,0 @@ -""" -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 ansys.aedt.core import Maxwell3d -from ansys.aedt.core import generate_unique_project_name -import os -import tempfile - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# Create temporary directory -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create temporary directory. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -############################################################################### -# 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 in graphical mode. - -m3d = Maxwell3d(project=generate_unique_project_name(), - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical) - -############################################################################### -# Set up Maxwell solution -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Set up the Maxwell solution to DC. - -m3d.solution_type = m3d.SOLUTIONS.Maxwell3d.ElectroDCConduction - -############################################################################### -# Create magnet -# ~~~~~~~~~~~~~ -# Create a magnet. - -magnet = m3d.modeler.create_box(origin=[7, 4, 22], sizes=[10, 5, 30], name="Magnet", material="copper") - -############################################################################### -# Create setup and assign voltage -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create the setup and assign a voltage. - -m3d.assign_voltage(magnet.faces, 0) -m3d.create_setup() - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -m3d.plot(show=False, output_file=os.path.join(temp_dir.name, "Image.jpg"), plot_air_objects=True) - -############################################################################### -# Solve setup -# ~~~~~~~~~~~ -# Solve the setup. - -m3d.analyze() - -############################################################################### -# Compute mass center -# ~~~~~~~~~~~~~~~~~~~ -# Compute mass center using the fields calculator. - -m3d.post.ofieldsreporter.EnterScalarFunc("X") -m3d.post.ofieldsreporter.EnterVol(magnet.name) -m3d.post.ofieldsreporter.CalcOp("Mean") -m3d.post.ofieldsreporter.AddNamedExpression("CM_X", "Fields") -m3d.post.ofieldsreporter.EnterScalarFunc("Y") -m3d.post.ofieldsreporter.EnterVol(magnet.name) -m3d.post.ofieldsreporter.CalcOp("Mean") -m3d.post.ofieldsreporter.AddNamedExpression("CM_Y", "Fields") -m3d.post.ofieldsreporter.EnterScalarFunc("Z") -m3d.post.ofieldsreporter.EnterVol(magnet.name) -m3d.post.ofieldsreporter.CalcOp("Mean") -m3d.post.ofieldsreporter.AddNamedExpression("CM_Z", "Fields") -m3d.post.ofieldsreporter.CalcStack("clear") - -############################################################################### -# Get mass center -# ~~~~~~~~~~~~~~~ -# Get mass center using the fields calculator. - -xval = m3d.post.get_scalar_field_value("CM_X") -yval = m3d.post.get_scalar_field_value("CM_Y") -zval = m3d.post.get_scalar_field_value("CM_Z") - -############################################################################### -# 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 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 the project and close AEDT. - -m3d.save_project() -m3d.release_desktop(close_projects=True, close_desktop=True) -temp_dir.cleanup() diff --git a/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py b/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py deleted file mode 100644 index 7befa8f3478..00000000000 --- a/examples/03-Maxwell/Maxwell_Transformer_Coreloss.py +++ /dev/null @@ -1,98 +0,0 @@ -""" -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 ansys.aedt.core import downloads -from ansys.aedt.core.generic.general_methods import generate_unique_folder_name -from ansys.aedt.core import Maxwell3d -from ansys.aedt.core.generic.constants import unit_converter -from ansys.aedt.core.generic.general_methods import read_csv_pandas - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -################################################################################# -# 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) -freq_curve_csv_100kHz = downloads.download_file("core_loss_transformer", "mf3_100kHz.csv", temp_folder) -freq_curve_csv_200kHz = downloads.download_file("core_loss_transformer", "mf3_200kHz.csv", temp_folder) -freq_curve_csv_400kHz = downloads.download_file("core_loss_transformer", "mf3_400kHz.csv", temp_folder) -freq_curve_csv_700kHz = downloads.download_file("core_loss_transformer", "mf3_700kHz.csv", temp_folder) -freq_curve_csv_1MHz = downloads.download_file("core_loss_transformer", "mf3_1MHz.csv", temp_folder) - -data = read_csv_pandas(input_file=freq_curve_csv_25kHz) -curves_csv_25kHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) -data = read_csv_pandas(input_file=freq_curve_csv_100kHz) -curves_csv_100kHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) -data = read_csv_pandas(input_file=freq_curve_csv_200kHz) -curves_csv_200kHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) -data = read_csv_pandas(input_file=freq_curve_csv_400kHz) -curves_csv_400kHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) -data = read_csv_pandas(input_file=freq_curve_csv_700kHz) -curves_csv_700kHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) -data = read_csv_pandas(input_file=freq_curve_csv_1MHz) -curves_csv_1MHz = list(zip(data[data.columns[0]], - data[data.columns[1]])) - -############################################################################### -# Launch AEDT -# ~~~~~~~~~~~ -# Launch AEDT in graphical mode. - -m3d = Maxwell3d(project=aedt_file, - design="02_3D eddycurrent_CmXY_for_thermal", - version=aedt_version, - new_desktop=True, - non_graphical=False) - -############################################################################### -# 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. - -mat = m3d.materials.add_material("newmat") -freq_25kHz = unit_converter(25, unit_system="Freq", input_units="kHz", output_units="Hz") -freq_100kHz = unit_converter(100, unit_system="Freq", input_units="kHz", output_units="Hz") -freq_200kHz = unit_converter(200, unit_system="Freq", input_units="kHz", output_units="Hz") -freq_400kHz = unit_converter(400, unit_system="Freq", input_units="kHz", output_units="Hz") -freq_700kHz = unit_converter(700, unit_system="Freq", input_units="kHz", output_units="Hz") -pv = {freq_25kHz: curves_csv_25kHz, - freq_100kHz: curves_csv_100kHz, - freq_200kHz: curves_csv_200kHz, - freq_400kHz: curves_csv_400kHz, - freq_700kHz: curves_csv_700kHz} -m3d.materials[mat.name].set_coreloss_at_frequency(points_list_at_freq=pv, - coefficient_setup="kw_per_cubic_meter", - core_loss_model_type="Power Ferrite") -coefficients = m3d.materials[mat.name].get_core_loss_coefficients(points_at_frequency=pv, - coefficient_setup="kw_per_cubic_meter") - -################################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Save the project and close AEDT. - -m3d.save_project() -m3d.release_desktop() diff --git a/examples/03-Maxwell/RMxprt.py b/examples/03-Maxwell/RMxprt.py deleted file mode 100644 index 08d59b61cd8..00000000000 --- a/examples/03-Maxwell/RMxprt.py +++ /dev/null @@ -1,156 +0,0 @@ -""" -Rmxprt: Create and export motor -------------------------------- -This example uses PyAEDT to create an Rmxprt project and export to Maxwell 2D -Keywords: Rmxprt, Maxwell2D -""" -import os.path -import tempfile - -import ansys.aedt.core - - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -################################################################################## -# Launch AEDT and Rmxprt -# ~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT and Rmxprt after first setting up the project name. -# As solution type we will use ASSM (Adjust-Speed Syncronous Machine). - - -app = ansys.aedt.core.Rmxprt( - version=aedt_version, - new_desktop=True, - close_on_exit=True, - solution_type="ASSM", - project=os.path.join(temp_dir.name, "ASSM.aedt"), -) - -################################################################################## -# Define Machine settings -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Define global machine settings. - -app.general["Number of Poles"] = 4 -app.general["Rotor Position"] = "Inner Rotor" -app.general["Frictional Loss"] = "12W" -app.general["Windage Loss"] = "0W" -app.general["Reference Speed"] = "1500rpm" -app.general["Control Type"] = "DC" -app.general["Circuit Type"] = "Y3" - - -################################################################################## -# Define circuit settings -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Define circuit settings. - -app.circuit["Trigger Pulse Width"] = "120deg" -app.circuit["Transistor Drop"] = "2V" -app.circuit["Diode Drop"] = "2V" - - -################################################################################## -# Stator -# ~~~~~~ -# Define stator, slot and windings settings. - -app.stator["Outer Diameter"] = "122mm" -app.stator["Inner Diameter"] = "75mm" -app.stator["Length"] = "65mm" -app.stator["Stacking Factor"] = 0.95 -app.stator["Steel Type"] = "steel_1008" -app.stator["Number of Slots"] = 24 -app.stator["Slot Type"] = 2 - -app.stator.properties.children["Slot"].props["Auto Design"] = False -app.stator.properties.children["Slot"].props["Hs0"] = "0.5mm" -app.stator.properties.children["Slot"].props["Hs1"] = "1.2mm" -app.stator.properties.children["Slot"].props["Hs2"] = "8.2mm" -app.stator.properties.children["Slot"].props["Bs0"] = "2.5mm" -app.stator.properties.children["Slot"].props["Bs1"] = "5.6mm" -app.stator.properties.children["Slot"].props["Bs2"] = "7.6mm" - -app.stator.properties.children["Winding"].props["Winding Layers"] = 2 -app.stator.properties.children["Winding"].props["Parallel Branches"] = 1 -app.stator.properties.children["Winding"].props["Conductors per Slot"] = 52 -app.stator.properties.children["Winding"].props["Coil Pitch"] = 5 -app.stator.properties.children["Winding"].props["Number of Strands"] = 1 - -################################################################################## -# Rotor -# ~~~~~ -# Define rotor and pole settings. - -app.rotor["Outer Diameter"] = "74mm" -app.rotor["Inner Diameter"] = "26mm" -app.rotor["Length"] = "65mm" -app.rotor["Stacking Factor"] = 0.95 -app.rotor["Steel Type"] = "steel_1008" -app.rotor["Pole Type"] = 1 - -app.rotor.properties.children["Pole"].props["Embrace"] = 0.7 -app.rotor.properties.children["Pole"].props["Offset"] = 0 -app.rotor.properties.children["Pole"].props["Magnet Type"] = ["Material:=", "Alnico9"] -app.rotor.properties.children["Pole"].props["Magnet Thickness"] = "3.5mm" - -################################################################################## -# Setup -# ~~~~~ -# Create a setup and define main settings. - -setup = app.create_setup() -setup.props["RatedVoltage"] = "220V" -setup.props["RatedOutputPower"] = "550W" -setup.props["RatedSpeed"] = "1500rpm" -setup.props["OperatingTemperature"] = "75cel" - - -setup.analyze() - -################################################################################## -# Export to Maxwell -# ~~~~~~~~~~~~~~~~~ -# After the project is solved we can export in Maxwell 2D or Maxwell 3D. - -m2d = app.create_maxwell_design(setup_name=setup.name, maxwell_2d=True) - -m2d.plot(show=False, output_file=os.path.join(temp_dir.name, "Image.jpg"), plot_air_objects=True) - - -################################################################################## -# Rmxprt settings export -# ~~~~~~~~~~~~~~~~~~~~~~ -# All Rmxprt settings can be exported in a json file and reused for another -# project with import function. - -config = app.export_configuration(os.path.join(temp_dir.name, "assm.json")) -app2 = ansys.aedt.core.Rmxprt(project="assm_test2",solution_type=app.solution_type, design="from_configuration") -app2.import_configuration(config) - - - -################################################################################## -# Save and Close Desktop -# ~~~~~~~~~~~~~~~~~~~~~~ -# Save and Close Desktop. - -m2d.save_project(os.path.join(temp_dir.name, "Maxwell_project.aedt")) - -m2d.release_desktop() - -########################## -# Cleanup -# ~~~~~~~ -# -# All project files are saved in the folder ``temp_dir.name``. If you've run this example as a Jupyter notebook you -# can retrieve those project files. The following cell removes all temporary files, including the project folder. - -temp_dir.cleanup() \ No newline at end of file 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/04-Icepak/Icepak_3DComponents_Example.py b/examples/04-Icepak/Icepak_3DComponents_Example.py deleted file mode 100644 index 4b6bcf2a865..00000000000 --- a/examples/04-Icepak/Icepak_3DComponents_Example.py +++ /dev/null @@ -1,180 +0,0 @@ -""" -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 ansys.aedt.core import Icepak, generate_unique_folder_name, downloads, settings -import os - -# Download needed files - -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. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Create heatsink -# ~~~~~~~~~~~~~~~ -# Open a new project in non-graphical mode. - -ipk = Icepak(project=os.path.join(temp_folder, "Heatsink.aedt"), - version=aedt_version, - non_graphical=non_graphical, - close_on_exit=True, - new_desktop=True) - -# Remove air region created by default because it is not needed as the heatsink will be exported as a 3DComponent. - -ipk.modeler.get_object_from_name("Region").delete() - -# Definition of heatsink with boxes -hs_base = ipk.modeler.create_box(origin=[0, 0, 0], sizes=[37.5, 37.5, 2], name="HS_Base") -hs_base.material_name = "Al-Extruded" -hs_fin = ipk.modeler.create_box(origin=[0, 0, 2], sizes=[37.5, 1, 18], name="HS_Fin1") -hs_fin.material_name = "Al-Extruded" -hs_fin.duplicate_along_line([0, 3.65, 0], nclones=11) - -ipk.plot(show=False, output_file=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(origin=[-2, -2, -3], sizes=[41.5, 41.5, 24]) -mesh_box.model = False -mesh_region = ipk.mesh.assign_mesh_region([mesh_box.name]) -mesh_region.UserSpecifiedSettings = True -mesh_region.MaxElementSizeX = "5mm" -mesh_region.MaxElementSizeY = "5mm" -mesh_region.MaxElementSizeZ = "1mm" -mesh_region.MinElementsInGap = "4" -mesh_region.MaxLevels = "2" -mesh_region.BufferLayers = "1" -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 - -ipk.monitor.assign_point_monitor(point_monitor_position, monitor_quantity=["Temperature", "HeatFlux"], - 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"), name="Heatsink", - export_auxiliary=True) -ipk.close_project(save=False) - -############################################################################### -# Create QFP -# ~~~~~~~~~~ -# Download and open a project containing a QPF. -ipk = Icepak(project=qfp_temp_name) -ipk.plot(show=False, output_file=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("PowerDissipationDataset", x_datalist, y_datalist, z=None, v=None, is_project_dataset=False, - x_unit="cel", y_unit="W", v_unit="") - -# Assign source power condition to the die. -ipk.create_source_power( - "DieSource", - thermal_dependent_dataset="PowerDissipationDataset", - source_name="DieSource" -) - -# Assign thickness to the die attach surface. -ipk.create_conduting_plate(face_id="Die_Attach", - thermal_specification="Thickness", - shell_conduction=True, - thickness="0.05mm", - solid_material="Epoxy Resin-Typical", - bc_name="Die_Attach", - ) - -# 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"), name="QFP", - export_auxiliary=True, datasets=["PowerDissipationDataset"]) -ipk.release_desktop(False, False) - -############################################################################### -# Create electronic package -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Download and open a project containing the electronic package. -ipk = Icepak(project=package_temp_name, - version=aedt_version, - non_graphical=non_graphical) -ipk.plot(show=False, output_file=os.path.join(temp_folder, "electronic_package_missing_obj.jpg")) - -# 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]], - name="HeatsinkCS", - reference_cs="Global", - x_pointing=[1, 0, 0], - y_pointing=[0, 1, 0], -) -heatsink_obj = ipk.modeler.insert_3d_component( - input_file=os.path.join(temp_folder, "componentLibrary", "Heatsink.a3dcomp"), coordinate_system="HeatsinkCS", - auxiliary_parameters=True) - -QFP2_obj = ipk.modeler.insert_3d_component(input_file=os.path.join(temp_folder, "componentLibrary", "QFP.a3dcomp"), - coordinate_system="Global", auxiliary_parameters=True) -ipk.plot(show=False, output_file=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]], - name="PCB_Assembly", - reference_cs="Global", - x_pointing=[1, 0, 0], - y_pointing=[0, 1, 0], -) - -# 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(input_file=os.path.join(temp_folder, "componentLibrary", "PCBAssembly.a3dcomp"), - name="PCBAssembly", coordinate_systems=["Global", "HeatsinkCS", "PCB_Assembly"], - reference_coordinate_system="PCB_Assembly", export_auxiliary=True) - -############################################################################### -# 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 deleted file mode 100644 index 5b4bd223e10..00000000000 --- a/examples/04-Icepak/Icepak_CSV_Import.py +++ /dev/null @@ -1,116 +0,0 @@ -""" -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. - -import os -import re -import csv -import ansys.aedt.core -from ansys.aedt.core.modules.boundary import BoundaryObject - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the project, open it, and save it to the temporary folder. - -temp_folder = ansys.aedt.core.generate_unique_folder_name() - -ipk = ansys.aedt.core.Icepak(project=os.path.join(temp_folder, "Icepak_CSV_Import.aedt"), - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical - ) - -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", material="FR-4_Ref") - -############################################################################### -# 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. -# Network blocks must have Rjb and Rjc values. -# Monitor points can be created for any types of block if the last column is assigned to be 1 (0 and 1 are the only options). -# -# 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 = ansys.aedt.core.downloads.download_file('icepak', 'blocks-list.csv', destination=temp_folder) - -with open(filename, 'r') as csv_file: - csv_reader = csv.DictReader(csv_file) - for row in csv_reader: - origin = [float(row["xs"]), float(row["ys"]), float(row["zs"])] # block starting point - dimensions = [float(row["xd"]), float(row["yd"]), float(row["zd"])] # block lengths in 3 dimensions - block_name = row["name"] # block name - - # Define material name - if row["matname"]: - material_name = row["matname"] - else: - material_name = "copper" - - # creates the block with the given name, coordinates, material, and type - block = ipk.modeler.create_box(origin, dimensions, name=block_name, material=material_name) - - # Assign boundary conditions - if row["block_type"] == "solid": - ipk.assign_solid_block(block_name, row["power"] + "W", block_name) - elif row["block_type"] == "network": - ipk.create_two_resistor_network_block(block_name, - board.name, - row["power"] + "W", - row["Rjb"], - row["Rjc"]) - else: - ipk.modeler[block.name].solve_inside = False - ipk.assign_hollow_block(block_name, assignment_type="Total Power", assignment_value=row["power"] + "W", - boundary_name=block_name) - - # Create temperature monitor points if assigned value is 1 in the last column of the csv file - if row["Monitor_point"] == '1': - ipk.monitor.assign_point_monitor_in_object( - row["name"], - monitor_quantity="Temperature", - monitor_name=row["name"]) - -############################################################################### -# 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 deleted file mode 100644 index b51476a40cc..00000000000 --- a/examples/04-Icepak/Icepak_ECAD_Import.py +++ /dev/null @@ -1,135 +0,0 @@ -""" -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 ansys.aedt.core -from ansys.aedt.core import Hfss3dLayout -from ansys.aedt.core import settings -settings.enable_debug_grpc_api_logger = True -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the project, open it, and save it to the temporary folder. - -temp_folder = ansys.aedt.core.generate_unique_folder_name() - -ipk = ansys.aedt.core.Icepak(project=os.path.join(temp_folder, "Icepak_ECAD_Import.aedt"), - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical - ) - -ipk.autosave_disable() # Saves the project - -############################################################################### -# Import the IDF files -# ~~~~~~~~~~~~~~~~~~~~ -# Sample *.bdf and *.ldf files are presented here. -# -# -# -# -# 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 = ansys.aedt.core.downloads.download_file('icepak/Icepak_ECAD_Import/A1_uprev.aedb','edb.def',temp_folder) -board_path = ansys.aedt.core.downloads.download_file('icepak/Icepak_ECAD_Import/','A1.bdf',temp_folder) -library_path = ansys.aedt.core.downloads.download_file('icepak/Icepak_ECAD_Import/','A1.ldf',temp_folder) - -ipk.import_idf(board_path, library_path=None, control_path=None, - filter_cap=False, filter_ind=False, filter_res=False, - filter_height_under=None, filter_height_exclude_2d=False, - power_under=None, create_filtered_as_non_model=False, - high_surface_thick='0.07mm', low_surface_thick='0.07mm', - internal_thick='0.07mm', internal_layer_number=2, - high_surface_coverage=30, low_surface_coverage=30, - internal_layer_coverage=30, trace_material='Cu-Pure', - substrate_material='FR-4', create_board=True, - model_board_as_rect=False, model_device_as_rect=True, - cutoff_height='5mm', component_lib='') - -############################################################################### -# 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 - -ipk.delete_design(name='PCB_temp', fallback_design=None) # deleting the dummy layout from the original project - -# 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 the PCB object from IDF import. - -ipk.modeler.delete_objects_containing("IDF_BoardOutline", False) - -############################################################################### -# Compute power budget -# ~~~~~~~~~~~~~~~~~~~~ - -# Creates a setup to be able to calculate the power -ipk.create_setup("setup1") - -power_budget, total = ipk.post.power_budget("W") -print(total) - -############################################################################### -# 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 deleted file mode 100644 index 28cfa5bc3de..00000000000 --- a/examples/04-Icepak/Icepak_Example.py +++ /dev/null @@ -1,117 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the project, open it, and save it to the temporary folder. - -temp_folder = ansys.aedt.core.generate_unique_folder_name() -project_temp_name = ansys.aedt.core.downloads.download_icepak(temp_folder) - -ipk = ansys.aedt.core.Icepak(project=project_temp_name, - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical - ) - -ipk.autosave_disable() - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -ipk.plot(show=False, output_file=os.path.join(temp_folder, "Graphics_card.jpg"), plot_air_objects=False) - -############################################################################### -# 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 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 a mesh region to the heat sink and CPU. - -mesh_region = ipk.mesh.assign_mesh_region(assignment=["HEAT_SINK", "CPU"]) -mesh_region.UserSpecifiedSettings = True -mesh_region.MaxElementSizeX = "3.35mm" -mesh_region.MaxElementSizeY = "1.75mm" -mesh_region.MaxElementSizeZ = "2.65mm" -mesh_region.MaxLevels = "2" -mesh_region.update() - -############################################################################### -# Assign point monitor -# ~~~~~~~~~~~~~~~~~~~~ -# Assign a point monitor and set it up. - -ipk.assign_point_monitor(point_position=["-35mm", "3.6mm", "-86mm"], monitor_name="TemperatureMonitor1") -ipk.assign_point_monitor(point_position=["80mm", "14.243mm", "-55mm"], monitor_type="Speed") -setup1 = ipk.create_setup() -setup1.props["Flow Regime"] = "Turbulent" -setup1.props["Convergence Criteria - Max Iterations"] = 5 -setup1.props["Linear Solver Type - Pressure"] = "flex" -setup1.props["Linear Solver Type - Temperature"] = "flex" -ipk.save_project() - -############################################################################### -# 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] -surflist += [i.id for i in ipk.modeler["MEMORY1_1"].faces] -surflist += [i.id for i in ipk.modeler["ALPHA_MAIN_PCB"].faces] - -plot5 = ipk.post.create_fieldplot_surface(surflist, "SurfTemperature") - -ipk.analyze() - -############################################################################### -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT. - -ipk.release_desktop(True, True) diff --git a/examples/04-Icepak/Readme.txt b/examples/04-Icepak/Readme.txt deleted file mode 100644 index f7bc280fad1..00000000000 --- a/examples/04-Icepak/Readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -Icepak examples -~~~~~~~~~~~~~~~ -These examples use PyAEDT to show end-to-end workflows for Icepak. This includes -schematic generation, setup, and thermal postprocessing. - diff --git a/examples/04-Icepak/Sherlock_Example.py b/examples/04-Icepak/Sherlock_Example.py deleted file mode 100644 index a55c2eead1e..00000000000 --- a/examples/04-Icepak/Sherlock_Example.py +++ /dev/null @@ -1,207 +0,0 @@ -""" -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 -import os -import ansys.aedt.core -import datetime - -# Set paths -project_folder = ansys.aedt.core.generate_unique_folder_name() -input_dir = ansys.aedt.core.downloads.download_sherlock(destination=project_folder) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 input variables. The following code creates all input variables that are needed -# to run this example. - -material_name = "MaterialExport.csv" -component_properties = "TutorialBoardPartsList.csv" -component_step = "TutorialBoard.stp" -aedt_odb_project = "SherlockTutorial.aedt" -aedt_odb_design_name = "PCB" - -############################################################################### -# Launch AEDT -# ~~~~~~~~~~~ -# Launch AEDT 2024 R2 in graphical mode. - -d = ansys.aedt.core.launch_desktop(version=aedt_version, non_graphical=non_graphical, new_desktop=True) - -start = time.time() -material_list = os.path.join(input_dir, material_name) -component_list = os.path.join(input_dir, component_properties) -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") -component_name = "from_ODB" - -############################################################################### -# Create Icepak project -# ~~~~~~~~~~~~~~~~~~~~~ -# Create an Icepak project. - -ipk = ansys.aedt.core.Icepak(project=project_name) - -############################################################################### -# Disable autosave to speed up import -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Disable autosave to speed up the import. - -d.disable_autosave() - -############################################################################### -# 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 an offset coordinate system to match ODB++ with the -# Sherlock STEP file. - -bb = ipk.modeler.user_defined_components[component_name+"1"].bounding_box -stackup_thickness = bb[-1] - bb[2] -ipk.modeler.create_coordinate_system( - origin=[0, 0, stackup_thickness / 2], mode="view", view="XY" -) - -############################################################################### -# Import CAD file -# ~~~~~~~~~~~~~~~ -# Import a CAD file and delete the CAD "pcb" object as the ECAD is already in the design. - -ipk.modeler.import_3d_cad(file_path, refresh_all_ids=False) -ipk.modeler.delete_objects_containing("pcb", False) - -############################################################################### -# Modify air region -# ~~~~~~~~~~~~~ -# Modify air region dimensions. - -ipk.mesh.global_mesh_region.global_region.padding_values = [20, 20, 20, 20, 300, 300] - -############################################################################### -# Assign materials -# ~~~~~~~~~~~~~~~~ -# Assign materials from Sherlock file. - -ipk.assignmaterial_from_sherlock_files( - component_file=component_list, material_file=material_list -) - -############################################################################### -# 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. - -all_objects = ipk.modeler.object_names - -############################################################################### -# Assign power blocks -# ~~~~~~~~~~~~~~~~~~~ -# Assign power blocks from the Sherlock file. - -total_power = ipk.assign_block_from_sherlock_file(csv_name=component_list) - -############################################################################### -# Assign openings -# ~~~~~~~~~~~~~~~~~~~ -# Assign opening boundary condition to all the faces of the region. -ipk.assign_openings(ipk.modeler.get_object_faces("Region")) - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model again now that materials are assigned. - -ipk.plot( - show=False, - output_file=os.path.join(project_folder, "Sherlock_Example.jpg"), - plot_air_objects=False, - plot_as_separate_objects=False -) - -############################################################################### -# Set up mesh settings -# ~~~~~~~~~~~~~~~~~ -# Mesh settings that is tailored for PCB - -ipk.globalMeshSettings(3, gap_min_elements='1', noOgrids=True, MLM_en=True, - MLM_Type='2D', edge_min_elements='2', object='Region') - -############################################################################### -# Numerical settings -# ~~~~~~~~~~~~~~~~~ - -setup1 = ipk.create_setup() -setup1.props["Solution Initialization - Y Velocity"] = "1m_per_sec" -setup1.props["Radiation Model"] = "Discrete Ordinates Model" -setup1.props["Include Gravity"] = True -setup1.props["Secondary Gradient"] = True -setup1.props["Convergence Criteria - Max Iterations"] = 100 - -############################################################################### -# Check for intersections -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Check for intersections using validation and fix them by -# assigning priorities. - -ipk.assign_priority_on_intersections() - -############################################################################### -# Compute power budget -# ~~~~~~~~~~~~~~~~~~~~ - -power_budget, total = ipk.post.power_budget("W") -print(total) - -############################################################################### -# 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/05-Q3D/Q2D_Armoured_Cable.py b/examples/05-Q3D/Q2D_Armoured_Cable.py deleted file mode 100644 index 71a959717ac..00000000000 --- a/examples/05-Q3D/Q2D_Armoured_Cable.py +++ /dev/null @@ -1,255 +0,0 @@ -""" -Q2D: Cable parameter identification ---------------------------------------------------- -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 `_ - -""" -################################################################################# -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ - -import ansys.aedt.core -import math - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -################################################################################# -# Initialize core strand dimensions and positions -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize cable sizing - radii in mm. - -c_strand_radius = 2.575 -cable_n_cores = 4 -core_n_strands = 6 -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 radii of further structures incrementally adding thicknesses. - -filling_radius = 1.4142 * (core_xy_coord + 3 * c_strand_radius + core_xlpe_ins_thickness + 0.5) -inner_sheath_radius = filling_radius + 0.75 -armour_thickness = 3 -armour_radius = inner_sheath_radius + armour_thickness -outer_sheath_radius = armour_radius + 2 - -################################################################################# -# 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 that contain all the definitions for the design -# variables and output variables. - -core_params = { - "n_cores": str(cable_n_cores), - "n_strands_core": str(core_n_strands), - "c_strand_radius": str(c_strand_radius) + 'mm', - "c_strand_xy_coord": str(core_xy_coord) + 'mm' -} -outer_params = { - "filling_radius": str(filling_radius) + 'mm', - "inner_sheath_radius": str(inner_sheath_radius) + 'mm', - "armour_radius": str(armour_radius) + 'mm', - "outer_sheath_radius": str(outer_sheath_radius) + 'mm' -} -armour_params = { - "armour_centre_pos": str(armour_centre_pos) + 'mm', - "arm_strand_rad": str(arm_strand_rad) + 'mm', - "n_arm_strands": str(n_arm_strands) -} - -################################################################################# -# Initialize Q2D -# ~~~~~~~~~~~~~~ -# Initialize Q2D, providing the version, path to the project, and the design -# name and type. - -project_name = 'Q2D_ArmouredCableExample' -q2d_design_name = '2D_Extractor_Cable' -setup_name = "MySetupAuto" -sweep_name = "sweep1" -tb_design_name = 'CableSystem' -q2d = ansys.aedt.core.Q2d(project=project_name, design=q2d_design_name, version=aedt_version) - -########################################################## -# Define variables from dictionaries -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define design variables from the created dictionaries. - -for k, v in core_params.items(): - q2d[k] = v -for k, v in outer_params.items(): - q2d[k] = v -for k, v in armour_params.items(): - q2d[k] = v - -########################################################## -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# 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) - -mat_pe_cable_grade = q2d.materials.add_material("plastic_pe_cable_grade") -mat_pe_cable_grade.conductivity = "1.40573e-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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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', material='copper') -c2_id = c1_id.duplicate_along_line(vector=['0mm', '2.0*c_strand_radius', '0mm'], nclones=2) -mod2D.duplicate_around_axis(c2_id, axis="Z", angle=360 / core_n_strands, clones=6) -c_unite_name = mod2D.unite(q2d.get_all_conductors_names()) - -fill_id = mod2D.create_circle(['0mm', '0mm', '0mm'], '3*c_strand_radius', name='c_strand_fill', - material='plastic_pp_carbon_fiber') -fill_id.color = (255, 255, 0) -xlpe_id = mod2D.create_circle(['0mm', '0mm', '0mm'], '3*c_strand_radius+' + str(core_xlpe_ins_thickness) + 'mm', - name='c_strand_xlpe', - material='plastic_pe_cable_grade') -xlpe_id.color = (0, 128, 128) - -mod2D.set_working_coordinate_system('Global') -all_obj_names = q2d.get_all_conductors_names() + q2d.get_all_dielectrics_names() -mod2D.duplicate_around_axis(all_obj_names, axis="Z", angle=360 / cable_n_cores, clones=4) -cond_names = q2d.get_all_conductors_names() - -##################################################################################### -# Create geometry for filling object -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -filling_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'filling_radius', name='Filling', - material='plastic_pp_carbon_fiber') -filling_id.color = (255, 255, 180) - -##################################################################################### -# Create geometry for inner sheath object -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -inner_sheath_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'inner_sheath_radius', name='InnerSheath', - material='PVC plastic') -inner_sheath_id.color = (0, 0, 0) - -##################################################################################### -# Create geometry for armature fill -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -arm_fill_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'armour_radius', name='ArmourFilling', - material='plastic_pp_carbon_fiber') -arm_fill_id.color = (255, 255, 255) - -##################################################################################### -# Create geometry for outer sheath -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -outer_sheath_id = mod2D.create_circle(['0mm', '0mm', '0mm'], 'outer_sheath_radius', name='OuterSheath', - material='PVC plastic') -outer_sheath_id.color = (0, 0, 0) - -##################################################################################### -# Create geometry for armature steel strands -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -arm_strand_1_id = mod2D.create_circle(['0mm', 'armour_centre_pos', '0mm'], '1.1mm', name='arm_strand_1', - material='steel_stainless') -arm_strand_1_id.color = (128, 128, 64) -arm_strand_1_id.duplicate_around_axis('Z', '360deg/n_arm_strands', clones='n_arm_strands') -arm_strand_names = mod2D.get_objects_w_string('arm_strand') - -##################################################################################### -# Create region -# ~~~~~~~~~~~~~ - -region = q2d.modeler.create_region([500, 500, 500, 500]) -region.material_name = "vacuum" - -########################################################## -# Assign conductors and reference ground -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -obj = [q2d.modeler.get_object_from_name(i) for i in cond_names] -[q2d.assign_single_conductor(assignment=i, name='C1' + str(obj.index(i) + 1), conductor_type='SignalLine') for i - in obj] -obj = [q2d.modeler.get_object_from_name(i) for i in arm_strand_names] -q2d.assign_single_conductor(assignment=obj, name="gnd", conductor_type="ReferenceGround") -mod2D.fit_all() - -########################################################## -# Assign design settings -# ~~~~~~~~~~~~~~~~~~~~~~ - -lumped_length = "100m" -q2d_des_settings = q2d.design_settings -q2d_des_settings['LumpedLength'] = lumped_length - -########################################################## -# Insert setup and frequency sweep -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -q2d_setup = q2d.create_setup(name=setup_name) -q2d_sweep = q2d_setup.add_sweep(name=sweep_name) - -########################################################## -# Analyze setup -# ~~~~~~~~~~~~~ - -# q2d.analyze(name=name) - -################################################################### -# Add a Simplorer/Twin Builder design and the Q3D dynamic component -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -tb = ansys.aedt.core.TwinBuilder(design=tb_design_name) - -########################################################## -# Add a Q3D dynamic component -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -tb.add_q3d_dynamic_component(project_name, q2d_design_name, setup_name, sweep_name, coupling_matrix_name="Original", - model_depth=lumped_length) - -########################################################## -# 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 deleted file mode 100644 index fa13f1d4763..00000000000 --- a/examples/05-Q3D/Q2D_Example_CPWG.py +++ /dev/null @@ -1,214 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Launch AEDT and 2D Extractor -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT 2023 R2 in graphical mode and launch 2D Extractor. This example -# uses SI units. - -q = ansys.aedt.core.Q2d(version=aedt_version, - non_graphical=non_graphical, - new_desktop=True, - project=ansys.aedt.core.generate_unique_name("pyaedt_q2d_example"), - design="coplanar_waveguide") - -############################################################################### -# Define variables -# ~~~~~~~~~~~~~~~~ -# Define variables. - -e_factor = "e_factor" -sig_bot_w = "sig_bot_w" -co_gnd_w = "gnd_w" -clearance = "clearance" -cond_h = "cond_h" -d_h = "d_h" -sm_h = "sm_h" - -for var_name, var_value in { - "sig_bot_w": "150um", - "e_factor": "2", - "gnd_w": "500um", - "clearance": "150um", - "cond_h": "50um", - "d_h": "150um", - "sm_h": "20um", -}.items(): - q[var_name] = var_value - -delta_w_half = "({0}/{1})".format(cond_h, e_factor) -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 and define the layer heights. - -layer_1_lh = 0 -layer_1_uh = cond_h -layer_2_lh = layer_1_uh + "+" + d_h -layer_2_uh = layer_2_lh + "+" + cond_h - -############################################################################### -# Create signal -# ~~~~~~~~~~~~~ -# Create a signal. - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [sig_bot_w, layer_2_lh, 0]], name="signal") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [sig_top_w, layer_2_uh, 0]]) -q.modeler.move(assignment=[top_line_obj], vector=[delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) -q.modeler.move(assignment=[base_line_obj], vector=["{}+{}".format(co_gnd_w, clearance), 0, 0]) - -############################################################################### -# Create coplanar ground -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create a coplanar ground. - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]], name="co_gnd_left") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]]) -q.modeler.move(assignment=[top_line_obj], vector=[delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]], name="co_gnd_right") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]]) -q.modeler.move(assignment=[top_line_obj], vector=[delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) -q.modeler.move(assignment=[base_line_obj], vector=["{}+{}*2+{}".format(co_gnd_w, clearance, sig_bot_w), 0, 0]) - -############################################################################### -# Create reference ground plane -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a reference ground plane. - -q.modeler.create_rectangle(origin=[0, layer_1_lh, 0], sizes=[model_w, cond_h], name="ref_gnd") - -############################################################################### -# Create dielectric -# ~~~~~~~~~~~~~~~~~ -# Create a dielectric. - -q.modeler.create_rectangle( - origin=[0, layer_1_uh, 0], sizes=[model_w, d_h], name="Dielectric", material="FR4_epoxy" -) - -############################################################################### -# Create conformal coating -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a conformal coating. - -sm_obj_list = [] -ids = [1, 2, 3] -if aedt_version >= "2023.1": - ids = [0, 1, 2] - -for obj_name in ["signal", "co_gnd_left", "co_gnd_right"]: - obj = q.modeler.get_object_from_name(obj_name) - e_obj_list = [] - for i in ids: - e_obj = q.modeler.create_object_from_edge(obj.edges[i]) - e_obj_list.append(e_obj) - e_obj_1 = e_obj_list[0] - q.modeler.unite(e_obj_list) - new_obj = q.modeler.sweep_along_vector(e_obj_1.id, [0, sm_h, 0]) - sm_obj_list.append(e_obj_1) - -new_obj = q.modeler.create_rectangle(origin=[co_gnd_w, layer_2_lh, 0], sizes=[clearance, sm_h]) -sm_obj_list.append(new_obj) - -new_obj = q.modeler.create_rectangle(origin=[co_gnd_w, layer_2_lh, 0], sizes=[clearance, sm_h]) -q.modeler.move([new_obj], [sig_bot_w + "+" + clearance, 0, 0]) -sm_obj_list.append(new_obj) - -sm_obj = sm_obj_list[0] -q.modeler.unite(sm_obj_list) -sm_obj.material_name = "SolderMask" -sm_obj.color = (0, 150, 100) -sm_obj.name = "solder_mask" - -############################################################################### -# Assign conductor -# ~~~~~~~~~~~~~~~~ -# Assign a conductor to the signal. - -obj = q.modeler.get_object_from_name("signal") -q.assign_single_conductor(assignment=[obj], name=obj.name, conductor_type="SignalLine", solve_option="SolveOnBoundary", - units="mm") - -############################################################################### -# 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"]] -q.assign_single_conductor(assignment=obj, name="gnd", conductor_type="ReferenceGround", solve_option="SolveOnBoundary", - units="mm") - -############################################################################### -# 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 the setup, analyze it, and plot solution data. - -setup = q.create_setup(name="new_setup") - -sweep = setup.add_sweep(name="sweep1", sweep_type="Discrete") -sweep.props["RangeType"] = "LinearStep" -sweep.props["RangeStart"] = "1GHz" -sweep.props["RangeStep"] = "100MHz" -sweep.props["RangeEnd"] = "5GHz" -sweep.props["SaveFields"] = False -sweep.props["SaveRadFields"] = False -sweep.props["Type"] = "Interpolating" - -sweep.update() - -q.analyze() - -a = q.post.get_solution_data(expressions="Z0(signal,signal)", context="Original") -a.plot() - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Save the project and close AEDT. - -home = os.path.expanduser("~") -q.save_project(os.path.join(home, "Downloads", "pyaedt_example", q.project_name + ".aedt")) -q.release_desktop() diff --git a/examples/05-Q3D/Q2D_Example_Stripline.py b/examples/05-Q3D/Q2D_Example_Stripline.py deleted file mode 100644 index 864c2828722..00000000000 --- a/examples/05-Q3D/Q2D_Example_Stripline.py +++ /dev/null @@ -1,225 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False -project_path = ansys.aedt.core.generate_unique_project_name() - -############################################################################### -# Launch AEDT and 2D Extractor -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT 2023 R2 in graphical mode and launch 2D Extractor. This example -# uses SI units. - -q = ansys.aedt.core.Q2d(project=project_path, - design="differential_stripline", - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True - ) - -############################################################################### -# Define variables -# ~~~~~~~~~~~~~~~~ -# Define variables. - -e_factor = "e_factor" -sig_w = "sig_bot_w" -sig_gap = "sig_gap" -co_gnd_w = "gnd_w" -clearance = "clearance" -cond_h = "cond_h" -core_h = "core_h" -pp_h = "pp_h" - -for var_name, var_value in { - "e_factor": "2", - "sig_bot_w": "150um", - "sig_gap": "150um", - "gnd_w": "500um", - "clearance": "150um", - "cond_h": "17um", - "core_h": "150um", - "pp_h": "150um", - -}.items(): - q[var_name] = var_value - -delta_w_half = "({0}/{1})".format(cond_h, e_factor) -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 and define the layer heights. - -layer_1_lh = 0 -layer_1_uh = cond_h -layer_2_lh = layer_1_uh + "+" + core_h -layer_2_uh = layer_2_lh + "+" + cond_h -layer_3_lh = layer_2_uh + "+" + pp_h -layer_3_uh = layer_3_lh + "+" + cond_h - -############################################################################### -# 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") -top_line_obj = q.modeler.create_polyline([[0, layer_2_uh, 0], [sig_top_w, layer_2_uh, 0]]) -q.modeler.move([top_line_obj], [delta_w_half, 0, 0]) -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 a negative signal. - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [sig_w, layer_2_lh, 0]], name="signal_n") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [sig_top_w, layer_2_uh, 0]]) -q.modeler.move(assignment=[top_line_obj], vector=[delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) -q.modeler.move(assignment=[base_line_obj], vector=["{}+{}+{}+{}".format(co_gnd_w, clearance, sig_w, sig_gap), 0, 0]) - -############################################################################### -# Create coplanar ground -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create a coplanar ground. - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]], name="co_gnd_left") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]]) -q.modeler.move([top_line_obj], [delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) - -base_line_obj = q.modeler.create_polyline(points=[[0, layer_2_lh, 0], [co_gnd_w, layer_2_lh, 0]], name="co_gnd_right") -top_line_obj = q.modeler.create_polyline(points=[[0, layer_2_uh, 0], [co_gnd_top_w, layer_2_uh, 0]]) -q.modeler.move(assignment=[top_line_obj], vector=[delta_w_half, 0, 0]) -q.modeler.connect([base_line_obj, top_line_obj]) -q.modeler.move(assignment=[base_line_obj], vector=["{}+{}*2+{}*2+{}".format(co_gnd_w, clearance, sig_w, sig_gap), 0, 0]) - -############################################################################### -# Create reference ground plane -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a reference ground plane. - -q.modeler.create_rectangle(origin=[0, layer_1_lh, 0], sizes=[model_w, cond_h], name="ref_gnd_u") -q.modeler.create_rectangle(origin=[0, layer_3_lh, 0], sizes=[model_w, cond_h], name="ref_gnd_l") - -############################################################################### -# Create dielectric -# ~~~~~~~~~~~~~~~~~ -# Create a dielectric. - -q.modeler.create_rectangle( - origin=[0, layer_1_uh, 0], sizes=[model_w, core_h], name="Core", material="FR4_epoxy" -) -q.modeler.create_rectangle( - origin=[0, layer_2_uh, 0], sizes=[model_w, pp_h], name="Prepreg", material="FR4_epoxy" -) -q.modeler.create_rectangle( - origin=[0, layer_2_lh, 0], sizes=[model_w, cond_h], name="Filling", material="FR4_epoxy" -) - -############################################################################### -# Assign conductors -# ~~~~~~~~~~~~~~~~~ -# Assign conductors to the signal. - -obj = q.modeler.get_object_from_name("signal_p") -q.assign_single_conductor(assignment=[obj], name=obj.name, conductor_type="SignalLine", solve_option="SolveOnBoundary", - units="mm") - -obj = q.modeler.get_object_from_name("signal_n") -q.assign_single_conductor(assignment=[obj], name=obj.name, conductor_type="SignalLine", solve_option="SolveOnBoundary", - units="mm") - -############################################################################### -# 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"]] -q.assign_single_conductor(assignment=obj, name="gnd", conductor_type="ReferenceGround", solve_option="SolveOnBoundary", - units="mm") - -############################################################################### -# 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 the differential pair. - -matrix = q.insert_reduced_matrix(operation_name=q.MATRIXOPERATIONS.DiffPair, assignment=["signal_p", "signal_n"], - reduced_matrix="diff_pair") - -############################################################################### -# Create setup, analyze, and plot -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a setup, analyze, and plot solution data. - -# Create a setup. -setup = q.create_setup(name="new_setup") - -# Add a sweep. -sweep = setup.add_sweep(name="sweep1", sweep_type="Discrete") -sweep.props["RangeType"] = "LinearStep" -sweep.props["RangeStart"] = "1GHz" -sweep.props["RangeStep"] = "100MHz" -sweep.props["RangeEnd"] = "5GHz" -sweep.props["SaveFields"] = False -sweep.props["SaveRadFields"] = False -sweep.props["Type"] = "Interpolating" -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(variable="sig_bot_w", start_point=75, end_point=100, step=5, variation_type="LinearStep") -parametric.add_variation(sweep_variable="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 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 deleted file mode 100644 index e18d9a949be..00000000000 --- a/examples/05-Q3D/Q3D_DC_IR.py +++ /dev/null @@ -1,258 +0,0 @@ -""" -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 ansys.aedt.core -from pyedb import Edb -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set up project files and path -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Download needed project file and set up temporary project directory. - -project_dir = ansys.aedt.core.generate_unique_folder_name() -aedb_project = ansys.aedt.core.downloads.download_file('edb/ANSYS-HSD_V1.aedb', destination=project_dir) -coil = ansys.aedt.core.downloads.download_file('inductance_3d_component', 'air_coil.a3dcomp') -res = ansys.aedt.core.downloads.download_file('resistors', 'Res_0402.a3dcomp') -project_name = ansys.aedt.core.generate_unique_name("HSD") -output_edb = os.path.join(project_dir, project_name + '_out.aedb') -output_q3d = os.path.join(project_dir, project_name + '_q3d.aedt') - -############################################################################### -# Open EDB -# ~~~~~~~~ -# Open the EDB project and create a cutout on the selected nets -# before exporting to Q3D. - -edb = Edb(aedb_project, edbversion=aedt_version) -edb.cutout(["1.2V_AVDLL_PLL", "1.2V_AVDDL", "1.2V_DVDDL", "NetR106_1"], - ["GND"], - output_aedb_path=output_edb, - use_pyaedt_extent_computing=True, - ) -edb.layout_validation.disjoint_nets("GND", keep_only_main_net=True) -############################################################################### -# Identify pin positions -# ~~~~~~~~~~~~~~~~~~~~~~ -# Identify [x,y] pin locations on the components to define where to assign sources -# and sinks for Q3D. - -pin_u11_scl = [i for i in edb.components["U11"].pins.values() if i.net_name == "1.2V_AVDLL_PLL"] -pin_u9_1 = [i for i in edb.components["U9"].pins.values() if i.net_name == "1.2V_AVDDL"] -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 -# ~~~~~~~~~~~~~~~~~~ -# 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) - -location_u9_1_scl = [i * 1000 for i in pin_u9_1[0].position] -location_u9_1_scl.append(edb.components["U9"].upper_elevation * 1000) - -location_u9_2_scl = [i * 1000 for i in pin_u9_2[0].position] -location_u9_2_scl.append(edb.components["U9"].upper_elevation * 1000) - -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 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] -location_l4_1.append(edb.components["L4"].upper_elevation * 1000) - -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. Then, open EDT in HFSS 3D Layout to generate the 3D model. -edb.save_edb_as(output_edb) -edb.close_edb() - -h3d = ansys.aedt.core.Hfss3dLayout(output_edb, version=aedt_version, non_graphical=False, new_desktop=True) - -############################################################################### -# 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 -# ~~~~~~~~ -# Launch the newly created q3d project. - -q3d = ansys.aedt.core.Q3d(output_q3d) -q3d.modeler.delete("GND") -q3d.delete_all_nets() - -############################################################################### -# 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, coordinate_system="L2") -comp.rotate(q3d.AXIS.Z, -90) -comp.parameters["n_turns"] = "3" -comp.parameters["d_wire"] = "100um" -q3d.modeler.set_working_coordinate_system("Global") -q3d.modeler.create_coordinate_system(location_l4_1, name="L4") -comp2 = q3d.modeler.insert_3d_component(coil, coordinate_system="L4") -comp2.rotate(q3d.AXIS.Z, -90) -comp2.parameters["n_turns"] = "3" -comp2.parameters["d_wire"] = "100um" -q3d.modeler.set_working_coordinate_system("Global") - -q3d.modeler.set_working_coordinate_system("Global") -q3d.modeler.create_coordinate_system(location_r106_1, name="R106") -comp3 = q3d.modeler.insert_3d_component(res, geometry_parameters={'$Resistance': 2000}, coordinate_system="R106") -comp3.rotate(q3d.AXIS.Z, -90) - -q3d.modeler.set_working_coordinate_system("Global") - -############################################################################### -# 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")) -q3d.modeler.delete(q3d.modeler.get_objects_by_material("Solder Resist")) - -objs_copper = q3d.modeler.get_objects_by_material("copper") -objs_copper_names = [i.name for i in objs_copper] -q3d.plot(assignment=objs_copper_names, show=False, output_file=os.path.join(q3d.working_directory, "Q3D.jpg"), - plot_as_separate_objects=False, plot_air_objects=False) - -############################################################################### -# 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) -source_f3= q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_r106, 0.1) -sources_objs = [source_f1, source_f2, source_f3] -q3d.auto_identify_nets() - -identified_net = q3d.nets[0] - -q3d.sink(sink_f, net_name=identified_net) - -source1 = q3d.source(source_f1, net_name=identified_net) - -source2 = q3d.source(source_f2, net_name=identified_net) -source3 = q3d.source(source_f3, net_name=identified_net) -sources_bounds = [source1, source2, source3] - -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 a setup and a frequency sweep from DC to 2GHz. -# Analyze project. - -setup = q3d.create_setup() -setup.dc_enabled = True -setup.capacitance_enabled = False -setup.ac_rl_enabled = False -setup.props["SaveFields"] = True -setup.props["DC"]["Cond"]["MaxPass"]=3 -setup.analyze() - -############################################################################### -# Field Calculator -# ~~~~~~~~~~~~~~~~ -# We will create a named expression using field calculator. - -drop_name = "Vdrop3_3" -fields = q3d.ofieldsreporter -q3d.ofieldsreporter.CalcStack("clear") -q3d.ofieldsreporter.EnterQty("Phidc") -q3d.ofieldsreporter.EnterScalar(3.3) -q3d.ofieldsreporter.CalcOp("+") -q3d.ofieldsreporter.AddNamedExpression(drop_name, "DC R/L Fields") - -############################################################################### -# Phi plot -# ~~~~~~~~ -# Compute ACL solutions and plot them. - -plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), - quantity=drop_name, - intrinsics={"Freq": "1GHz"}) - -q3d.post.plot_field_from_fieldplot(plot1.name, project_path=q3d.working_directory, mesh_plot=False, image_format="jpg", - view="isometric", show=False, plot_cad_objs=False, log_scale=False) - -############################################################################### -# 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 - - curves.append("V{}".format(source_bound.name)) - - q3d.ofieldsreporter.CalcStack("clear") - q3d.ofieldsreporter.CopyNamedExprToStack(drop_name) - q3d.ofieldsreporter.EnterSurf(source_sheet_name) - 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, - variations={"Freq": "1GHz"}, - report_category="DC R/L Fields", - ) -for curve in curves: - print(data.data_real(curve)) - -############################################################################### -# 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 deleted file mode 100644 index 2c3d2ea48d9..00000000000 --- a/examples/05-Q3D/Q3D_Example.py +++ /dev/null @@ -1,158 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# 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. - -ansys.aedt.core.settings.enable_debug_logger = True -ansys.aedt.core.settings.enable_debug_methods_argument_logger = True -ansys.aedt.core.settings.enable_debug_internal_methods_logger = False - - -############################################################################### -# Launch AEDT and Q3D Extractor -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT 2023 R2 in graphical mode and launch Q3D Extractor. -# This example uses SI units. - -q = ansys.aedt.core.Q3d(project=ansys.aedt.core.generate_unique_project_name(), - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True) - -############################################################################### -# 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", material="copper", xsection_type="Rectangle", - xsection_width="5mm", xsection_height="1mm") -q.modeler["Bar1"].color = (255, 0, 0) - -q.modeler.create_polyline([[0, -15, 0], [-150, -15, 0]], name="Bar2", material="aluminum", xsection_type="Rectangle", - xsection_width="5mm", xsection_height="1mm") -q.modeler["Bar2"].color = (0, 255, 0) - -q.modeler.create_polyline([[0, -30, 0], [-175, -30, 0], [-175, -10, 0]], name="Bar3", material="copper", - xsection_type="Rectangle", xsection_width="5mm", xsection_height="1mm") -q.modeler["Bar3"].color = (0, 0, 255) - -q.modeler.create_box([50, 30, -0.5], [-250, -100, -3], name="substrate", material="FR4_epoxy") -q.modeler["substrate"].color = (128, 128, 128) -q.modeler["substrate"].transparency = 0.8 - -q.plot(show=False, output_file=os.path.join(q.working_directory, "Q3D.jpg"), plot_air_objects=False) - -############################################################################### -# 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", direction=q.AxisDir.XPos, name="Source1") -q.sink("Bar1", direction=q.AxisDir.XNeg, name="Sink1") - -q.source("Bar2", direction=q.AxisDir.XPos, name="Source2") -q.sink("Bar2", direction=q.AxisDir.XNeg, name="Sink2") -q.source("Bar3", direction=q.AxisDir.XPos, name="Source3") -bar3_sink = q.sink("Bar3", direction=q.AxisDir.YPos) -bar3_sink.name = "Sink3" - -############################################################################### -# Print information -# ~~~~~~~~~~~~~~~~~ -# Use the different methods available to print net and terminal information. - -print(q.nets) -print(q.net_sinks("Bar1")) -print(q.net_sinks("Bar2")) -print(q.net_sinks("Bar3")) -print(q.net_sources("Bar1")) -print(q.net_sources("Bar2")) -print(q.net_sources("Bar3")) - -############################################################################### -# Create setup -# ~~~~~~~~~~~~ -# Create a setup for Q3D Extractor and add a sweep that defines the adaptive -# frequency value. - -setup1 = q.create_setup(props={"AdaptiveFreq": "100MHz"}) -sw1 = setup1.add_sweep() -sw1.props["RangeStart"] = "1MHz" -sw1.props["RangeEnd"] = "100MHz" -sw1.props["RangeStep"] = "5MHz" -sw1.update() - -############################################################################### -# 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) -data_plot_mutual = q.get_traces_for_plot(get_self_terms=False, get_mutual_terms=True, category="C") - -############################################################################### -# 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, plot_type="Data Table", context="Original") - -############################################################################### -# Solve setup -# ~~~~~~~~~~~ -# Solve the setup. - -q.analyze() -q.save_project() - -############################################################################### -# 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") -a.plot() - -############################################################################### -# 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. - -ansys.aedt.core.settings.enable_debug_logger = False -ansys.aedt.core.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 deleted file mode 100644 index ae4eb2a297f..00000000000 --- a/examples/05-Q3D/Q3D_from_EDB.py +++ /dev/null @@ -1,154 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Setup project files and path -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Download of needed project file and setup of temporary project directory. - -project_dir = ansys.aedt.core.generate_unique_folder_name() -aedb_project = ansys.aedt.core.downloads.download_file('edb/ANSYS-HSD_V1.aedb',destination=project_dir) - -project_name = ansys.aedt.core.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 the edb project and created a cutout on the selected nets -# before exporting to Q3D. - -edb = ansys.aedt.core.Edb(aedb_project, edbversion=aedt_version) -edb.cutout(["CLOCK_I2C_SCL", "CLOCK_I2C_SDA"], ["GND"], output_aedb_path=output_edb, - use_pyaedt_extent_computing=True, ) - -############################################################################### -# 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. - -pin_u13_scl = [i for i in edb.components["U13"].pins.values() if i.net_name == "CLOCK_I2C_SCL"] -pin_u1_scl = [i for i in edb.components["U1"].pins.values() if i.net_name == "CLOCK_I2C_SCL"] -pin_u13_sda = [i for i in edb.components["U13"].pins.values() if i.net_name == "CLOCK_I2C_SDA"] -pin_u1_sda = [i for i in edb.components["U1"].pins.values() if i.net_name == "CLOCK_I2C_SDA"] - -############################################################################### -# 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) - -location_u1_scl = [i * 1000 for i in pin_u1_scl[0].position] -location_u1_scl.append(edb.components["U1"].upper_elevation * 1000) - -location_u13_sda = [i * 1000 for i in pin_u13_sda[0].position] -location_u13_sda.append(edb.components["U13"].upper_elevation * 1000) - -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, close Edb and open it in Hfss 3D Layout to generate the 3D model. - -edb.save_edb() -edb.close_edb() - -h3d = ansys.aedt.core.Hfss3dLayout(output_edb, version=aedt_version, non_graphical=True, new_desktop=True) - -############################################################################### -# 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 -# ~~~~~~~~ -# Launch the newly created q3d project and plot it. - -q3d = ansys.aedt.core.Q3d(output_q3d) -q3d.plot(assignment=["CLOCK_I2C_SCL", "CLOCK_I2C_SDA"], show=False, - output_file=os.path.join(q3d.working_directory, "Q3D.jpg"), plot_air_objects=False) - -############################################################################### -# 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, assignment="CLOCK_I2C_SCL") -q3d.source(f1, net_name="CLOCK_I2C_SCL") -f1 = q3d.modeler.get_faceid_from_position(location_u13_sda, assignment="CLOCK_I2C_SDA") -q3d.source(f1, net_name="CLOCK_I2C_SDA") -f1 = q3d.modeler.get_faceid_from_position(location_u1_scl, assignment="CLOCK_I2C_SCL") -q3d.sink(f1, net_name="CLOCK_I2C_SCL") -f1 = q3d.modeler.get_faceid_from_position(location_u1_sda, assignment="CLOCK_I2C_SDA") -q3d.sink(f1, net_name="CLOCK_I2C_SDA") - -############################################################################### -# Create Setup -# ~~~~~~~~~~~~ -# Create a setup and a frequency sweep from DC to 2GHz. -# Analyze project. - -setup = q3d.create_setup() -setup.dc_enabled = True -setup.capacitance_enabled = False -sweep = setup.add_sweep() -sweep.add_subrange("LinearStep", 0, end=2, count=0.05, unit="GHz", save_single_fields=False, clear=True) -setup.analyze() - -############################################################################### -# 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 -# ~~~~~~~~~~ -# 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 -# ~~~~~~~~~~ -# 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/Readme.txt deleted file mode 100644 index 1d4f3398872..00000000000 --- a/examples/05-Q3D/Readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -2D Extractor and Q3D Extractor examples -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -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. - diff --git a/examples/06-Multiphysics/Circuit-HFSS-Icepak-coupling.py b/examples/06-Multiphysics/Circuit-HFSS-Icepak-coupling.py deleted file mode 100644 index 8ec5fcd37e4..00000000000 --- a/examples/06-Multiphysics/Circuit-HFSS-Icepak-coupling.py +++ /dev/null @@ -1,319 +0,0 @@ -""" -Multiphysics: Circuit-HFSS-Icepak coupling workflow ---------------------------------------------------- -This example demonstrates how to create a two-way coupling between Circuit-HFSS designs and Icepak. - -Let's consider a design where some components are simulated in HFSS with a full 3D model, -while others are simulated in Circuit as lumped elements. The electrical simulation is done by -placing the HFSS design into a Circuit design as a subcomponent and by connecting the lumped components to -its ports. - -The purpose of the workflow is to perform a thermal simulation of the Circuit-HFSS design, -creating a two-way coupling with Icepak that allows running multiple iterations. -The losses from both designs are accounted for: EM losses are evaluated by the HFSS solver -and fed into Icepak via a direct link, while losses from the lumped components in the Circuit -design are evaluated analytically and must be manually set into the Icepak boundary. - -On the way back of the coupling, temperature information is handled differently for HFSS and Circuit. -For HFSS, a temperature map is exported from the Icepak design and used to create a 3D dataset; -then the material properties in the HFSS design are updated based on this dataset. -For Circuit, the average temperature of the lumped components is extracted from the Icepak design -and used to update the temperature-dependent characteristics of the lumped components in Circuit. - -In this example, the Circuit design contains only a resistor component, -with temperature-dependent resistance described by this formula: 0.162*(1+0.004*(TempE-TempE0)), -where TempE is the current temperature and TempE0 is the ambient temperature. -The HFSS design includes only a cylinder with temperature-dependent material conductivity, -defined by a 2D dataset. The resistor and the cylinder have matching resistances. - - -The workflow steps are as follows: - -1. Solve the HFSS design. -2. Refresh the dynamic link and solve the Circuit design. -3. Push excitations (HFSS design results are scaled automatically). -4. Extract the resistor's power loss value from the Circuit design. -5. Set the resistor's power loss value in the Icepak design (block thermal condition). -6. Solve the Icepak design. -7. Export the temperature map from the Icepak design and create a new 3D dataset with it. -8. Update material properties in the HFSS design based on the new dataset. -9. Extract the average temperature of the resistor from the Icepak design. -10. Update the resistance value in the Circuit design based on the new resistor average temperature. - -""" - -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. -from ansys.aedt.core import Circuit -from ansys.aedt.core import Hfss -from ansys.aedt.core import Icepak -from ansys.aedt.core import downloads -import os - - -############################################################################### -# Download and open project -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Download the project archive. Save it to the temporary folder. -project_path = downloads.download_file("circuit_hfss_icepak", "Circuit-HFSS-Icepak-workflow.aedtz") - -############################################################################### -# Open the project and get the Circuit design. -circuit = Circuit( - project=project_path, - new_desktop_session=True, - specified_version=242, - non_graphical=False -) - -############################################################################### -# Set the name of the resistor in Circuit. -resistor_body_name = "Circuit_Component" - -############################################################################### -# Set the name of the cylinder body in HFSS. -device3D_body_name = "Device_3D" - - -############################################################################### -# Get the Hfss design and prepare the material for the thermal link -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Get the Hfss design. -hfss = Hfss(project=circuit.project_name) - -############################################################################### -# Create a new material that will be used to set the temperature map on it. -# The material is created by duplicating the material assigned to the cylinder. -material_name = hfss.modeler.objects_by_name[device3D_body_name].material_name -new_material_name = material_name + "_dataset" -new_material = hfss.materials.duplicate_material(material=material_name, name=new_material_name) - -############################################################################### -# Save the conductivity value. It will be used later in the iterations. -old_conductivity = new_material.conductivity.value - -############################################################################### -# Assign the new material to the cylinder object in HFSS. -hfss.modeler.objects_by_name[device3D_body_name].material_name = new_material_name - -############################################################################### -# Since this material has a high conductivity, HFSS automatically deactivate "Solve Inside". -# It needs to be set back on as we need to evaluate the losses inside the cylinder. -hfss.modeler.objects_by_name[device3D_body_name].solve_inside = True - - -############################################################################### -# Get the Icepak design -# ~~~~~~~~~~~~~~~~~~~~~ -# Get the Icepak design. -icepak = Icepak(project=circuit.project_name) - - -############################################################################### -# Set the parameters for the iterations -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set the initial temperature to a value closer to the final one, to speed up the convergence. -circuit["TempE"] = "300cel" - -############################################################################### -# Set the maximum number of iterations. -max_iter = 5 - -############################################################################### -# Set the residual convergence criteria to stop the iterations. -temp_residual_limit = 0.02 -loss_residual_limit = 0.02 - -############################################################################### -# This variable will contain the iteration statistics. -stats = {} - - -############################################################################### -# Start the iterations -# ~~~~~~~~~~~~~~~~~~~~ -# Each for loop is a complete two-way iteration. -# The code is thoroughly commented. -# Please read the inline comments carefully for a full understanding. -for cp_iter in range(1, max_iter + 1): - stats[cp_iter] = {} - - - # Step 1: Solve the Hfss design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Solve the Hfss design. - hfss.analyze() - - - # Step 2: Refresh the dynamic link and solve the Circuit design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Find the HFSS subcomponent in Circuit. - # This information is required by refresh_dynamic_link and push_excitations methods. - hfss_component_name = "" - hfss_instance_name = "" - for component in circuit.modeler.components.components.values(): - if ( - component.model_name is not None - and hfss.design_name in component.model_name - ): - hfss_component_name = component.model_name - hfss_instance_name = component.refdes - break - if not hfss_component_name or not hfss_instance_name: - raise "Hfss component not found in Circuit design" - - # Refresh the dynamic link. - circuit.modeler.schematic.refresh_dynamic_link(name=hfss_component_name) - - # Solve the Circuit design. - circuit.analyze() - - - # Step 3: Push excitations (HFSS design results are scaled automatically) - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Push excitations. - circuit.push_excitations(instance=hfss_instance_name) - - - # Step 4: Extract the resistor's power loss value from the Circuit design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Evaluate power loss on resistor. - r_losses = circuit.post.get_solution_data(expressions="0.5*mag(I(I1)*V(V1))").data_magnitude()[0] - - # Save the losses in the stats. - stats[cp_iter]["losses"] = r_losses - - - # Step 5: Set the resistor's power loss value in the Icepak design (block thermal condition) - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Find the Solid Block boundary in Icepak. - boundaries = icepak.boundaries - boundary = None - for bb in boundaries: - if bb.name == "Block1": - boundary = bb - break - if not boundary: - raise "Block boundary not defined in Icepak design." - - # Set the resistor's power loss in the Block Boundary. - boundary.props["Total Power"] = str(r_losses) + "W" - - - # Step 6: Solve the Icepak design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Clear linked data, otherwise Icepak continues to run simulation with the initial losses. - icepak.clear_linked_data() - - # Solve the Icepak design. - icepak.analyze() - - - # Step 7: Export the temperature map from the Icepak and create a new 3D dataset with it - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Export the temperature map into a file. - fld_filename = os.path.join( - icepak.working_directory, f"temperature_map_{cp_iter}.fld" - ) - icepak.post.export_field_file( - quantity="Temp", output_file=fld_filename, assignment="AllObjects", objects_type="Vol" - ) - - # Convert the fld file format into a dataset tab file compatible with dataset import. - # The existing header lines must be removed and replaced with a single header line - # containing the value unit. - with open(fld_filename, "r") as f: - lines = f.readlines() - - _ = lines.pop(0) - _ = lines.pop(0) - lines.insert(0, '"X" "Y" "Z" "cel"\n') - - basename, _ = os.path.splitext(fld_filename) - tab_filename = basename + "_dataset.tab" - - with open(tab_filename, "w") as f: - f.writelines(lines) - - # Import the 3D dataset. - dataset_name = f"temp_map_step_{cp_iter}" - hfss.import_dataset3d( - input_file=tab_filename, name=dataset_name, is_project_dataset=True - ) - - - # Step 8: Update material properties in the HFSS design based on the new dataset - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Set the new conductivity value. - new_material.conductivity.value = ( - f"{old_conductivity}*Pwl($TempDepCond,clp(${dataset_name},X,Y,Z))" - ) - - # Switch off the thermal modifier of the material, if any. - new_material.conductivity.thermalmodifier = None - - - # Step 9: Extract the average temperature of the resistor from the Icepak design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Get the mean temp value on the high resistivity object. - mean_temp = icepak.post.get_scalar_field_value( - quantity="Temp", scalar_function="Mean", object_name=resistor_body_name - ) - - # Save the temperature in the iteration stats. - stats[cp_iter]["temp"] = mean_temp - - - # Step 10: Update the resistance value in the Circuit design - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Set this temperature in circuit in variable TempE. - circuit["TempE"] = f"{mean_temp}cel" - - # Save the project - circuit.save_project() - - - # Check the convergence of the iteration - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Evaluate the relative residuals on temperature and losses. - # If the residuals are smaller than the threshold, set the convergence flag to `True`. - # Residuals are calculated starting from the second iteration. - converged = False - stats[cp_iter]["converged"] = converged - if cp_iter > 1: - delta_temp = abs(stats[cp_iter]["temp"] - stats[cp_iter-1]["temp"]) / abs(stats[cp_iter-1]["temp"]) - delta_losses = abs(stats[cp_iter]["losses"] - stats[cp_iter-1]["losses"]) / abs(stats[cp_iter-1]["losses"]) - if delta_temp <= temp_residual_limit and delta_losses <= loss_residual_limit: - converged = True - stats[cp_iter]["converged"] = converged - else: - delta_temp = None - delta_losses = None - - # Save the relative residuals in the iteration stats. - stats[cp_iter]["delta_temp"] = delta_temp - stats[cp_iter]["delta_losses"] = delta_losses - - # Exit from the loop if the convergence is reached. - if converged: - break - -############################################################################### -# Print the overall statistics -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Print the overall statistics for the multiphysic loop. -for i in stats: - txt = "yes" if stats[i]["converged"] else "no" - delta_temp = f"{stats[i]['delta_temp']:.4f}" if stats[i]['delta_temp'] is not None else "None" - delta_losses = f"{stats[i]['delta_losses']:.4f}" if stats[i]['delta_losses'] is not None else "None" - print( - f"Step {i}: temp={stats[i]['temp']:.3f}, losses={stats[i]['losses']:.3f}, " - f"delta_temp={delta_temp}, delta_losses={delta_losses}, " - f"converged={txt}" - ) - -############################################################################### -# Close Electronics Desktop -circuit.release_desktop() diff --git a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py b/examples/06-Multiphysics/Hfss_Icepak_Coupling.py deleted file mode 100644 index 556bcc5217f..00000000000 --- a/examples/06-Multiphysics/Hfss_Icepak_Coupling.py +++ /dev/null @@ -1,335 +0,0 @@ -""" -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 ansys.aedt.core -from ansys.aedt.core.post.pdf import AnsysReport - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# Open project -# ~~~~~~~~~~~~ -# Open the project. - -NewThread = True - -project_file = ansys.aedt.core.generate_unique_project_name() - -############################################################################### -# 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 = ansys.aedt.core.Hfss(project=project_file, - version=aedt_version, - non_graphical=non_graphical, - new_desktop=NewThread - ) - -############################################################################### -# 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. - -aedtapp["$coax_dimension"] = "100mm" -udp = aedtapp.modeler.Position(0, 0, 0) -aedtapp["inner"] = "3mm" - -############################################################################### -# Create coaxial and cylinders -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a coaxial and three cylinders. You can apply parameters -# directly using the :func:`ansys.aedt.core.modeler.cad.primitives_3d.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. - -# TODO: How does this work when two truesurfaces are defined? -o1 = aedtapp.modeler.create_cylinder(orientation=aedtapp.PLANE.ZX, origin=udp, radius="inner", height="$coax_dimension", - num_sides=0, name="inner") -o2 = aedtapp.modeler.create_cylinder(orientation=aedtapp.PLANE.ZX, origin=udp, radius=8, height="$coax_dimension", - num_sides=0, material="teflon_based") -o3 = aedtapp.modeler.create_cylinder(orientation=aedtapp.PLANE.ZX, origin=udp, radius=10, height="$coax_dimension", - num_sides=0, name="outer") - -############################################################################### -# Assign colors -# ~~~~~~~~~~~~~ -# Assign colors to each primitive. - -o1.color = (255, 0, 0) -o2.color = (0, 255, 0) -o3.color = (255, 0, 0) -o3.transparency = 0.8 -aedtapp.modeler.fit_all() - -############################################################################### -# 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. 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. - -aedtapp.mesh.assign_initial_mesh_from_slider(level=6) -aedtapp.mesh.assign_model_resolution(assignment=[o1.name, o3.name], defeature_length=None) -aedtapp.mesh.assign_length_mesh(assignment=o2.faces, inside_selection=False, maximum_length=1, maximum_elements=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. - -aedtapp.wave_port(assignment="inner", reference="outer", create_port_sheet=True, create_pec_cap=True, - integration_line=1, name="P1") -aedtapp.wave_port(assignment="inner", reference="outer", create_port_sheet=True, create_pec_cap=True, - integration_line=4, name="P2") - -port_names = aedtapp.get_all_sources() -aedtapp.modeler.fit_all() - -############################################################################### -# Create 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. - -aedtapp.set_active_design(aedtapp.design_name) -setup = aedtapp.create_setup("MySetup") -setup.props["Frequency"] = "1GHz" -setup.props["BasisOrder"] = 2 -setup.props["MaximumPasses"] = 1 - -############################################################################### -# Create sweep -# ~~~~~~~~~~~~ -# Create a sweep. A sweep is created with default values. - -sweepname = aedtapp.create_linear_count_sweep(setup="MySetup", units="GHz", start_frequency=0.8, stop_frequency=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. - -ipkapp = ansys.aedt.core.Icepak() -ipkapp.copy_solid_bodies_from(aedtapp) - -################################################################################ -# Link sources to EM losses -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Link sources to the EM losses. - -surfaceobj = ["inner", "outer"] -ipkapp.assign_em_losses(design=aedtapp.design_name, setup="MySetup", sweep="LastAdaptive", map_frequency="1GHz", - surface_objects=surfaceobj, parameters=["$coax_dimension", "inner"]) - -################################################################################# -# Edit gravity setting -# ~~~~~~~~~~~~~~~~~~~~ -# Edit the gravity setting if necessary because it is important for a fluid analysis. - -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 -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Edit or review the mesh parameters. After a mesh is created, you can access -# a mesh operation to edit or review parameter values. - -airbox = ipkapp.modeler.get_obj_id("Region") -ipkapp.modeler[airbox].display_wireframe = True -airfaces = ipkapp.modeler.get_object_faces(airbox) -ipkapp.assign_openings(airfaces) - -################################################################################ -# 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() -aedtapp.close_project(aedtapp.project_name) -aedtapp = ansys.aedt.core.Hfss(project_file) -ipkapp = ansys.aedt.core.Icepak() -ipkapp.solution_type = ipkapp.SOLUTIONS.Icepak.SteadyTemperatureAndFlow -ipkapp.modeler.fit_all() - -################################################################################ -# Solve Icepak project -# ~~~~~~~~~~~~~~~~~~~~ -# Solve the Icepak project and the HFSS sweep. - -setup1 = ipkapp.analyze_setup("SetupIPK") -aedtapp.save_project() -aedtapp.modeler.fit_all() -aedtapp.analyze_setup("MySetup") - -################################################################################ -# Generate field plots and export -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Generate field plots on the HFSS project and export them as images. - -cutlist = [ansys.aedt.core.constants.GLOBALCS.XY, ansys.aedt.core.constants.GLOBALCS.ZX, ansys.aedt.core.constants.GLOBALCS.YZ] -vollist = [o2.name] -setup_name = "MySetup : LastAdaptive" -quantity_name = "ComplexMag_E" -quantity_name2 = "ComplexMag_H" -intrinsic = {"Freq": "1GHz", "Phase": "0deg"} -surflist = aedtapp.modeler.get_object_faces("outer") -plot1 = aedtapp.post.create_fieldplot_surface(surflist, quantity_name2, setup_name, intrinsic) - -results_folder = os.path.join(aedtapp.working_directory, "Coaxial_Results_NG") -if not os.path.exists(results_folder): - os.mkdir(results_folder) - -aedtapp.post.plot_field_from_fieldplot(plot1.name, project_path=results_folder, mesh_plot=False, image_format="jpg", - view="isometric", show=False, plot_cad_objs=False, log_scale=False) - -################################################################################ -# 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)] - -animated = aedtapp.post.plot_animated_field(quantity="Mag_E", assignment=cutlist, plot_type="CutPlane", - setup=aedtapp.nominal_adaptive, - intrinsics={"Freq": "1GHz", "Phase": "0deg"}, variation_variable="Phase", - variations=phases, show=False, log_scale=True, export_gif=False, - export_path=results_folder) -animated.gif_file = os.path.join(aedtapp.working_directory, "animate.gif") -# animated.camera_position = [0, 0, 300] -# animated.focal_point = [0, 0, 0] -# Set off_screen to False to visualize the animation. -# animated.off_screen = False -animated.animate() - -endtime = time.time() - start -print("Total Time", endtime) - -################################################################################ -# 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 = "" -surflist = ipkapp.modeler.get_object_faces("inner") + ipkapp.modeler.get_object_faces("outer") -plot5 = ipkapp.post.create_fieldplot_surface(surflist, "SurfTemperature") - -aedtapp.save_project() - -################################################################################ -# Generate plots outside of AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Generate plots outside of AEDT using Matplotlib and NumPy. - -trace_names = aedtapp.get_traces_for_plot(category="S") -cxt = ["Domain:=", "Sweep"] -families = ["Freq:=", ["All"]] -my_data = aedtapp.post.get_solution_data(expressions=trace_names) -my_data.plot(trace_names, "db20", x_label="Frequency (Ghz)", y_label="SParameters(dB)", title="Scattering Chart", - snapshot_path=os.path.join(results_folder, "Touchstone_from_matplotlib.jpg")) - -################################################################################ -# Generate pdf report -# ~~~~~~~~~~~~~~~~~~~ -# Generate a pdf report with output of simultion. -report = AnsysReport(version=aedt_version, design_name=aedtapp.design_name, project_name=aedtapp.project_name) -report.create() -report.add_section() -report.add_chapter("Hfss Results") -report.add_sub_chapter("Field Plot") -report.add_text("This section contains Field plots of Hfss Coaxial.") -report.add_image(os.path.join(results_folder, plot1.name + ".jpg"), "Coaxial Cable") -report.add_page_break() -report.add_sub_chapter("S Parameters") -report.add_chart(my_data.intrinsics["Freq"], my_data.data_db20(), "Freq", trace_names[0], "S-Parameters") -report.add_image(os.path.join(results_folder, "Touchstone_from_matplotlib.jpg"), "Touchstone from Matplotlib") -report.add_section() -report.add_chapter("Icepak Results") -report.add_sub_chapter("Temperature Plot") -report.add_text("This section contains Multiphysics temperature plot.") -report.add_toc() -# 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 the project and release AEDT. - -aedtapp.release_desktop() diff --git a/examples/06-Multiphysics/Hfss_Mechanical.py b/examples/06-Multiphysics/Hfss_Mechanical.py deleted file mode 100644 index 0de9512d2b7..00000000000 --- a/examples/06-Multiphysics/Hfss_Mechanical.py +++ /dev/null @@ -1,163 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 the project. Save it to the temporary folder. - -project_temp_name = ansys.aedt.core.downloads.download_via_wizard(ansys.aedt.core.generate_unique_folder_name()) - -############################################################################### -# Start HFSS -# ~~~~~~~~~~ -# Start HFSS and initialize the PyAEDT object. - -hfss = ansys.aedt.core.Hfss(project=project_temp_name, version=aedt_version, non_graphical=non_graphical, - new_desktop=True) -pin_names = hfss.excitations -hfss.change_material_override(True) - -############################################################################### -# Start Circuit -# ~~~~~~~~~~~~~ -# Start Circuit and add the HFSS dynamic link component to it. - -circuit = ansys.aedt.core.Circuit() -hfss_comp = circuit.modeler.schematic.add_subcircuit_dynamic_link(hfss) - -############################################################################### -# 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. - -circuit.modeler.schematic.refresh_dynamic_link(hfss_comp.composed_name) -circuit.modeler.schematic.set_sim_option_on_hfss_subcircuit(hfss_comp) -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. 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]] -) -circuit.modeler.schematic.create_interface_port( - name="Excitation_2", location=[hfss_comp.pins[1].location[0], hfss_comp.pins[1].location[1]] -) -circuit.modeler.schematic.create_interface_port( - name="Port_1", location=[hfss_comp.pins[2].location[0], hfss_comp.pins[2].location[1]] -) -circuit.modeler.schematic.create_interface_port( - name="Port_2", location=[hfss_comp.pins[3].location[0], hfss_comp.pins[3].location[1]] -) - -voltage = 1 -phase = 0 -ports_list = ["Excitation_1", "Excitation_2"] -source = circuit.assign_voltage_sinusoidal_excitation_to_ports(ports_list) -source.ac_magnitude = voltage -source.phase = phase - -############################################################################### -# Create setup -# ~~~~~~~~~~~~ -# Create a setup. - -setup_name = "MySetup" -LNA_setup = circuit.create_setup(name=setup_name) -bw_start = 4.3 -bw_stop = 4.4 -n_points = 1001 -unit = "GHz" -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 the circuit and push excitations to the HFSS model to calculate the -# correct value of losses. - -circuit.analyze() -circuit.push_excitations(instance="S1", setup=setup_name) - - -############################################################################### -# Start Mechanical -# ~~~~~~~~~~~~~~~~ -# Start Mechanical and copy bodies from the HFSS project. - -mech = ansys.aedt.core.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 the convection to Mechanical. - -mech.assign_em_losses(design=hfss.design_name, setup=hfss.setups[0].name, sweep="LastAdaptive", - map_frequency=hfss.setups[0].props["Frequency"], surface_objects=hfss.get_all_conductors_names()) -diels = ["1_pd", "2_pd", "3_pd", "4_pd", "5_pd"] -for el in diels: - mech.assign_uniform_convection(assignment=[mech.modeler[el].top_face_y, mech.modeler[el].bottom_face_y], - convection_value=3) - -############################################################################### -# Plot model -# ~~~~~~~~~~ -# Plot the model. - -mech.plot(show=False, output_file=os.path.join(mech.working_directory, "Mech.jpg"), plot_air_objects=False) - -############################################################################### -# Solve and plot thermal results -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Solve and plot the thermal results. - -mech.create_setup() -mech.save_project() -mech.analyze() -surfaces = [] -for name in mech.get_all_conductors_names(): - surfaces.extend(mech.modeler.get_object_faces(name)) -mech.post.create_fieldplot_surface(assignment=surfaces, quantity="Temperature") - -############################################################################### -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT. - -mech.release_desktop(True, True) diff --git a/examples/06-Multiphysics/MRI.py b/examples/06-Multiphysics/MRI.py deleted file mode 100644 index 03cbb09e3ac..00000000000 --- a/examples/06-Multiphysics/MRI.py +++ /dev/null @@ -1,293 +0,0 @@ -""" -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 - -from ansys.aedt.core import Hfss, Mechanical, Icepak, downloads - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Set non-graphical mode -# ~~~~~~~~~~~~~~~~~~~~~~ -# Set non-graphical mode. ` -# You can set ``non_graphical`` either to ``True`` or ``False``. - -non_graphical = False - -############################################################################### -# 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"), version=aedt_version, non_graphical=non_graphical, - new_desktop=True) - -############################################################################### -# 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, -# and excitations -# ‒ 3D Components make it easy to reuse and share parts of a simulation - -hfss.modeler.insert_3d_component(os.path.join(project_path, "coil.a3dcomp")) - -############################################################################### -# 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( - report_type="Modal Solution Data", - expressions=im_traces, - isconvergence=True, - isrelativeconvergence=False, - conv_criteria=2.5, - use_cache_for_freq=False) -hfss.setups[0].props["MaximumPasses"] = 2 - -############################################################################### -# Edit Sources -# ~~~~~~~~~~~~ -# The 3D Component of the MRI Coil contains all the ports, -# but the sources for these ports are not yet defined. -# Browse to and select sources.csv. -# These sources were determined by tuning this coil at 63.8 MHz. -# Notice the “*input_scale” multiplier to allow quick adjustment of the coil excitation power. - -hfss.edit_sources_from_file(os.path.join(project_path, "sources.csv")) - -############################################################################### -# Run Simulation -# ~~~~~~~~~~~~~~ -# Save and analyze the project. - -hfss.save_project(os.path.join(project_path, "solved.aedt")) -hfss.analyze(cores=6) - -############################################################################### -# Plot SAR on cut plane in phantom -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Ensure that the SAR averaging method is set to Gridless -# Plot averagedSAR on GlobalYZ plane -# Draw Point1 at origin of the implant coordinate system - -hfss.sar_setup(-1, tissue_mass=1, material_density=1, average_sar_method=1) -hfss.post.create_fieldplot_cutplane(assignment="implant:YZ", quantity="Average_SAR", filter_objects=["implant_box"]) - -hfss.modeler.set_working_coordinate_system("implant") -hfss.modeler.create_point([0, 0, 0], name="Point1") - -hfss.post.plot_field(quantity="Average_SAR", assignment="implant:YZ", plot_type="CutPlane", show=False, - show_legend=False, filter_objects=["implant_box"]) - -############################################################################### -# Adjust Input Power to MRI Coil -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# The goal is to adjust the MRI coil’s input power, so that the averageSAR at Point1 is 1 W/kg -# Note that SAR and input power are linearly related -# To determine required input, calculate -# input_scale = 1/AverageSAR at Point1 - -sol_data = hfss.post.get_solution_data(expressions="Average_SAR", - primary_sweep_variable="Freq", - context="Point1", - report_category="Fields") -sol_data.data_real() - -hfss["input_scale"] = 1 / sol_data.data_real()[0] - -############################################################################### -# Phantom with Implant -# ~~~~~~~~~~~~~~~~~~~~ -# Import implant geometry. -# Subtract rod from implant_box. -# Assign titanium to the imported object rod. -# Analyze the project. - -hfss.modeler.import_3d_cad(os.path.join(project_path, "implant_rod.sat")) - -hfss.modeler["implant_box"].subtract("rod", keep_originals=True) -hfss.modeler["rod"].material_name = "titanium" -hfss.analyze(cores=6) -hfss.save_project() - -############################################################################### -# Thermal Simulation -# ~~~~~~~~~~~~~~~~~~ -# Initialize a new Mechanical Transient Thermal analysis. -# Mechanical Transient Thermal is available in AEDT from 2023 R2 as a Beta feature. - -mech = Mechanical(solution_type="Transient Thermal", version=aedt_version) - -############################################################################### -# Copy geometries -# ~~~~~~~~~~~~~~~ -# Copy bodies from the HFSS project. 3D Component will not be copied. - -mech.copy_solid_bodies_from(hfss) - -################################################################################ -# Link sources to EM losses -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Link sources to the EM losses. -# Assign external convection. - -exc = mech.assign_em_losses(design=hfss.design_name, setup=hfss.setups[0].name, sweep="LastAdaptive", - map_frequency=hfss.setups[0].props["Frequency"], - surface_objects=mech.get_all_conductors_names()) -mech.assign_uniform_convection(mech.modeler["Region"].faces, convection_value=1) - -################################################################################ -# Create Setup -# ~~~~~~~~~~~~ -# Create a new setup and edit properties. -# Simulation will be for 60 seconds. - -setup = mech.create_setup() -# setup.add_mesh_link("backgroundSAR") -# mech.create_dataset1d_design("PowerMap", [0, 239, 240, 360], [1, 1, 0, 0]) -# exc.props["LossMultiplier"] = "pwl(PowerMap,Time)" - -mech.modeler.set_working_coordinate_system("implant") -mech.modeler.create_point([0, 0, 0], name="Point1") -setup.props["Stop Time"] = 60 -setup.props["Time Step"] = "10s" -setup.props["SaveFieldsType"] = "Every N Steps" -setup.props["N Steps"] = "2" - -############################################################################### -# Analyze Mechanical -# ~~~~~~~~~~~~~~~~~~ -# Analyze the project. - -mech.analyze(cores=6) - -############################################################################### -# Plot fields -# ~~~~~~~~~~~ -# Plot Temperature on cut plane. -# Plot Temperature on point. - -mech.post.create_fieldplot_cutplane("implant:YZ", "Temperature", filter_objects=["implant_box"]) -mech.save_project() - -data = mech.post.get_solution_data("Temperature", primary_sweep_variable="Time", context="Point1", - report_category="Fields") -#data.plot() - -mech.post.plot_animated_field(quantity="Temperature", assignment="implant:YZ", plot_type="CutPlane", - intrinsics={"Time": "10s"}, variation_variable="Time", - variations=["10s", "20s", "30s", "40s", "50s", "60s"], - show=False, filter_objects=["implant_box"]) - -############################################################################### -# Thermal Simulation -# ~~~~~~~~~~~~~~~~~~ -# Initialize a new Icepak Transient Thermal analysis. - -ipk = Icepak(solution_type="Transient", version=aedt_version) -ipk.design_solutions.problem_type = "TemperatureOnly" - -############################################################################### -# Copy geometries -# ~~~~~~~~~~~~~~~ -# Copy bodies from the HFSS project. 3D Component will not be copied. - -ipk.modeler.delete("Region") -ipk.copy_solid_bodies_from(hfss) - -################################################################################ -# Link sources to EM losses -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Link sources to the EM losses. -# Assign external convection. - -exc = ipk.assign_em_losses(design=hfss.design_name, setup=hfss.setups[0].name, sweep="LastAdaptive", - map_frequency=hfss.setups[0].props["Frequency"], - surface_objects=ipk.get_all_conductors_names()) - -################################################################################ -# Create Setup -# ~~~~~~~~~~~~ -# Create a new setup and edit properties. -# Simulation will be for 60 seconds. - -setup = ipk.create_setup() - -setup.props["Stop Time"] = 60 -setup.props["N Steps"] = 2 -setup.props["Time Step"] = 5 -setup.props['Convergence Criteria - Energy'] = 1e-12 - -################################################################################ -# Mesh Region -# ~~~~~~~~~~~ -# Create a new mesh region and change accuracy level to 4. - -bound = ipk.modeler["implant_box"].bounding_box -mesh_box = ipk.modeler.create_box(bound[:3], [bound[3] - bound[0], bound[4] - bound[1], bound[5] - bound[2]]) -mesh_box.model = False -mesh_region = ipk.mesh.assign_mesh_region([mesh_box.name]) -mesh_region.UserSpecifiedSettings = False -mesh_region.Level = 4 -mesh_region.update() - -################################################################################ -# Point Monitor -# ~~~~~~~~~~~~~ -# Create a new point monitor. - -ipk.modeler.set_working_coordinate_system("implant") -ipk.monitor.assign_point_monitor([0, 0, 0], monitor_name="Point1") -ipk.assign_openings(ipk.modeler["Region"].top_face_z) - -############################################################################### -# Analyze and plot fields -# ~~~~~~~~~~~~~~~~~~~~~~~ -# Analyze the project. -# Plot temperature on cut plane. -# Plot temperature on monitor point. - -ipk.analyze(cores=4, tasks=4) -ipk.post.create_fieldplot_cutplane("implant:YZ", "Temperature", filter_objects=["implant_box"]) -ipk.save_project() - -data = ipk.post.get_solution_data("Point1.Temperature", primary_sweep_variable="Time", report_category="Monitor") -#data.plot() - -ipk.release_desktop(True, True) diff --git a/examples/06-Multiphysics/Maxwell3D_Icepak_2Way_Coupling.py b/examples/06-Multiphysics/Maxwell3D_Icepak_2Way_Coupling.py deleted file mode 100644 index 17919c5f64b..00000000000 --- a/examples/06-Multiphysics/Maxwell3D_Icepak_2Way_Coupling.py +++ /dev/null @@ -1,281 +0,0 @@ -""" -Multiphysics: Maxwell 3D - Icepak electrothermal analysis ---------------------------------------------------------- -This example uses PyAEDT to set up a simple Maxwell design consisting of a coil and a ferrite core. -Coil current is set to 100A, and coil resistance and ohmic loss are analyzed. -Ohmic loss is mapped to Icepak, and a thermal analysis is performed. Icepak calculates a temperature distribution, -and it is mapped back to Maxwell (2-way coupling). Coil resistance and ohmic loss are analyzed again in Maxwell. -Results are printed in AEDT Message Manager. -""" -########################################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import ansys.aedt.core -from ansys.aedt.core.generic.constants import AXIS - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################################################### -# 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. 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 = "Maxwell-Icepak-2way-Coupling" -maxwell_design_name = "1 Maxwell" -icepak_design_name = "2 Icepak" - -m3d = ansys.aedt.core.Maxwell3d( - project=project_name, - design=maxwell_design_name, - solution_type="EddyCurrent", - version=aedt_version, - non_graphical=non_graphical, -) - -############################################################################### -# Create geometry in Maxwell -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create the coil, coil terminal, core, and region. - -coil = m3d.modeler.create_rectangle( - orientation="XZ", origin=[70, 0, -11], sizes=[11, 110], name="Coil" -) - -coil.sweep_around_axis(axis=AXIS.Z) - -coil_terminal = m3d.modeler.create_rectangle( - orientation="XZ", origin=[70, 0, -11], sizes=[11, 110], name="Coil_terminal" -) - -core = m3d.modeler.create_rectangle( - orientation="XZ", origin=[45, 0, -18], sizes=[7, 160], name="Core" -) -core.sweep_around_axis(axis=AXIS.Z) - -# Magnetic flux is not concentrated by the core in +z-direction. Therefore, more padding is needed in that direction. -region = m3d.modeler.create_region(pad_percent=[20, 20, 500, 20, 20, 100]) - -############################################################################### -# Assign materials -# ~~~~~~~~~~~~~~~~ -# Create a material: Copper AWG40 Litz wire, strand diameter = 0.08mm, 24 parallel strands. -# Assign materials: Assign Coil to AWG40 copper, core to ferrite, and region to vacuum. - -no_strands = 24 -strand_diameter = 0.08 - -cu_litz = m3d.materials.duplicate_material("copper", "copper_litz") -cu_litz.stacking_type = "Litz Wire" -cu_litz.wire_diameter = str(strand_diameter) + "mm" -cu_litz.wire_type = "Round" -cu_litz.strand_number = no_strands - -m3d.assign_material(region.name, "vacuum") -m3d.assign_material(coil.name, "copper_litz") -m3d.assign_material(core.name, "ferrite") - -############################################################################### -# Assign excitation -# ~~~~~~~~~~~~~~~~~ -# Assign coil current, coil consists of 20 turns, total current 10A. -# Note that each coil turn consists of 24 parallel Litz strands, see above. - -no_turns = 20 -coil_current = 10 -m3d.assign_coil(["Coil_terminal"], conductors_number=no_turns, name="Coil_terminal") -m3d.assign_winding(is_solid=False, current=coil_current, name="Winding1") - -m3d.add_winding_coils(assignment="Winding1", coils=["Coil_terminal"]) - -############################################################################### -# Assign mesh operations -# ~~~~~~~~~~~~~~~~~~~~~~ -# Mesh operations are not necessary in eddy current solver because of auto-adaptive meshing. -# However, with appropriate mesh operations, less adaptive passes are needed. - -m3d.mesh.assign_length_mesh(["Core"], maximum_length=15, maximum_elements=None, name="Inside_Core") -m3d.mesh.assign_length_mesh(["Coil"], maximum_length=30, maximum_elements=None, name="Inside_Coil") - -############################################################################### -# Set conductivity temperature coefficient -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set conductivity as a function of temperature. Resistivity increases by 0.393% per K. - -cu_resistivity_temp_coefficient = 0.00393 -cu_litz.conductivity.add_thermal_modifier_free_form("1.0/(1.0+{}*(Temp-20))".format(cu_resistivity_temp_coefficient)) - -############################################################################### -# Set object temperature and enable feedback -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set the temperature of the objects to default temperature (22deg C) -# and enable temperature feedback for two-way coupling. - -m3d.modeler.set_objects_temperature(["Coil"]) - -############################################################################### -# Assign matrix -# ~~~~~~~~~~~~~ -# Resistance and inductance calculation. - -m3d.assign_matrix(["Winding1"], matrix_name="Matrix1") - -############################################################################### -# Create and analyze simulation setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Simulation frequency 150kHz. - -setup = m3d.create_setup(name="Setup1") -setup.props["Frequency"] = "150kHz" -m3d.analyze_setup("Setup1") - -############################################################################### -# Postprocessing -# ~~~~~~~~~~~~~~ -# Calculate analytical DC resistance and compare it with the simulated coil resistance, -# print them in the message manager, as well as ohmic loss in coil before temperature feedback. - -report = m3d.post.create_report(expressions="Matrix1.R(Winding1,Winding1)") -solution = report.get_solution_data() -resistance = solution.data_magnitude()[0] - -report_loss = m3d.post.create_report(expressions="StrandedLossAC") -solution_loss = report_loss.get_solution_data() -em_loss = solution_loss.data_magnitude()[0] - -# Analytical calculation of the DC resistance of the coil -cu_cond = float(cu_litz.conductivity.value) -# average radius of a coil turn = 0.125m -l_conductor = no_turns*2*0.125*3.1415 -# R = resistivity * length / area / no_strand -r_analytical_DC = (1.0 / cu_cond) * l_conductor / (3.1415 * (strand_diameter / 1000 / 2) ** 2) / no_strands - -# Print results in the Message Manager -m3d.logger.info("*******Coil analytical DC resistance = {:.2f}Ohm".format(r_analytical_DC)) -m3d.logger.info("*******Coil resistance at 150kHz BEFORE temperature feedback = {:.2f}Ohm".format(resistance)) -m3d.logger.info("*******Ohmic loss in coil BEFORE temperature feedback = {:.2f}W".format(em_loss / 1000)) - -############################################################################### -# Icepak design -# ~~~~~~~~~~~~~ -# Insert Icepak design, copy solid objects from Maxwell, and modify region dimensions. - -ipk = ansys.aedt.core.Icepak(design=icepak_design_name) -ipk.copy_solid_bodies_from(m3d, no_pec=False) - -# Set domain dimensions suitable for natural convection using the diameter of the coil -ipk.modeler["Region"].delete() -coil_dim = coil.bounding_dimension[0] -ipk.modeler.create_region(0, False) -ipk.modeler.edit_region_dimensions([coil_dim / 2, coil_dim / 2, coil_dim / 2, coil_dim / 2, coil_dim * 2, coil_dim]) - -############################################################################### -# Map coil losses -# ~~~~~~~~~~~~~~~ -# Map ohmic losses from Maxwell to the Icepak design. - -ipk.assign_em_losses(design="1 Maxwell", setup=m3d.setups[0].name, sweep="LastAdaptive", assignment=["Coil"]) - -############################################################################### -# Boundary conditions -# ~~~~~~~~~~~~~~~~~~~ -# Assign opening. - -faces = ipk.modeler["Region"].faces -face_names = [face.id for face in faces] -ipk.assign_free_opening(face_names, boundary_name="Opening1") - -############################################################################### -# Assign monitor -# ~~~~~~~~~~~~~~ -# Temperature monitor on the coil surface - -temp_monitor = ipk.assign_point_monitor([70, 0, 0], monitor_name="PointMonitor1") - -############################################################################### -# Icepak solution setup -# ~~~~~~~~~~~~~~~~~~~~~ - -solution_setup = ipk.create_setup() -solution_setup.props["Convergence Criteria - Max Iterations"] = 50 -solution_setup.props["Flow Regime"] = "Turbulent" -solution_setup.props["Turbulent Model Eqn"] = "ZeroEquation" -solution_setup.props["Radiation Model"] = "Discrete Ordinates Model" -solution_setup.props["Include Flow"] = True -solution_setup.props["Include Gravity"] = True -solution_setup.props["Solution Initialization - Z Velocity"] = "0.0005m_per_sec" -solution_setup.props["Convergence Criteria - Flow"] = 0.0005 -solution_setup.props["Flow Iteration Per Radiation Iteration"] = "5" - - -############################################################################### -# Add 2-way coupling and solve the project -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Enable mapping temperature distribution back to Maxwell. -# Default number Maxwell <--> Icepak iterations is 2, -# but for increased accuracy it can be increased (number_of_iterations). - -ipk.assign_2way_coupling() -ipk.analyze_setup(name=solution_setup.name) - -############################################################################### -# Postprocessing -# ~~~~~~~~~~~~~~ -# Plot temperature on the object surfaces. - -surface_list = [] -for name in ["Coil", "Core"]: - surface_list.extend(ipk.modeler.get_object_faces(name)) - -surf_temperature = ipk.post.create_fieldplot_surface(surface_list, quantity="SurfTemperature", - plot_name="Surface Temperature") - -velocity_cutplane = ipk.post.create_fieldplot_cutplane(assignment=["Global:XZ"], quantity="Velocity Vectors", - plot_name="Velocity Vectors") - -surf_temperature.export_image() -velocity_cutplane.export_image(orientation="right") - -report_temp = ipk.post.create_report(expressions="PointMonitor1.Temperature", primary_sweep_variable="X") -solution_temp = report_temp.get_solution_data() -temp = solution_temp.data_magnitude()[0] -m3d.logger.info("*******Coil temperature = {:.2f}deg C".format(temp)) - -############################################################################### -# Get new resistance from Maxwell -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Temperature of the coil increases, and consequently also coil resistance increases. - -report_new = m3d.post.create_report(expressions="Matrix1.R(Winding1,Winding1)") -solution_new = report_new.get_solution_data() -resistance_new = solution_new.data_magnitude()[0] -resistance_increase = (resistance_new - resistance)/resistance * 100 - -report_loss_new = m3d.post.create_report(expressions="StrandedLossAC") -solution_loss_new = report_loss_new.get_solution_data() -em_loss_new = solution_loss_new.data_magnitude()[0] - -m3d.logger.info("*******Coil resistance at 150kHz AFTER temperature feedback = {:.2f}Ohm".format(resistance_new)) -m3d.logger.info("*******Coil resistance increased by {:.2f}%".format(resistance_increase)) -m3d.logger.info("*******Ohmic loss in coil AFTER temperature feedback = {:.2f}W".format(em_loss_new/1000)) - -################################################################################## -# Release desktop -# ~~~~~~~~~~~~~~~ - -ipk.release_desktop(True, True) diff --git a/examples/06-Multiphysics/Readme.txt b/examples/06-Multiphysics/Readme.txt deleted file mode 100644 index d35019b7dbd..00000000000 --- a/examples/06-Multiphysics/Readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -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. diff --git a/examples/07-Circuit/Circuit_AMI.py b/examples/07-Circuit/Circuit_AMI.py deleted file mode 100644 index 11ee2ce73ee..00000000000 --- a/examples/07-Circuit/Circuit_AMI.py +++ /dev/null @@ -1,271 +0,0 @@ -""" -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. - -# sphinx_gallery_thumbnail_path = 'Resources/spectrum_plot.png' - -import os -from matplotlib import pyplot as plt -import numpy as np - -import ansys.aedt.core - -# Set local path to path for PyAEDT -temp_folder = ansys.aedt.core.generate_unique_folder_name() -project_path = ansys.aedt.core.downloads.download_file("ami", "ami_usb.aedtz", temp_folder) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################## -# 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 -NewThread = True - -############################################################################### -# 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:`ansys.aedt.core.Desktop` class initializes AEDT -# and starts the specified version in the specified mode. - -ansys.aedt.core.settings.enable_pandas_output = True -cir = ansys.aedt.core.Circuit(project=os.path.join(project_path), non_graphical=non_graphical, - version=aedt_version, new_desktop=NewThread) - -############################################################################### -# Solve AMI setup -# ~~~~~~~~~~~~~~~ -# Solve the transient setup. - -cir.analyze() - -############################################################################### -# Get AMI report -# ~~~~~~~~~~~~~~ -# Get AMI report data - -plot_name = "WaveAfterProbe" -cir.solution_type = "NexximAMI" -original_data = cir.post.get_solution_data(expressions=plot_name, domain="Time", - variations=cir.available_variations.nominal) -original_data_value = original_data.full_matrix_real_imag[0] -original_data_sweep = original_data.primary_sweep_values -print(original_data_value) - -############################################################################### -# 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 - -probe_name = "b_input_43" -source_name = "b_output4_42" -plot_type = "WaveAfterProbe" -setup_name = "AMIAnalysis" -ignore_bits = 100 -unit_interval = 0.1e-9 -sample_waveform = cir.post.sample_ami_waveform(setup=setup_name, probe=probe_name, source=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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create the plot from a start time to stop time in seconds - -tstop = 55e-9 -tstart = 50e-9 -scale_time = ansys.aedt.core.constants.unit_converter(1, unit_system="Time", input_units="s", - output_units=original_data.units_sweeps["Time"]) -scale_data = ansys.aedt.core.constants.unit_converter(1, unit_system="Voltage", input_units="V", - output_units=original_data.units_data[plot_name]) - -tstop_ns = scale_time * tstop -tstart_ns = scale_time * tstart - -for time in original_data_value[plot_name].index: - if tstart_ns <= time[0]: - start_index_original_data = time[0] - break -for time in original_data_value[plot_name][start_index_original_data:].index: - if time[0] >= tstop_ns: - stop_index_original_data = time[0] - break -for time in sample_waveform[0].index: - if tstart <= time: - sample_index = sample_waveform[0].index == time - start_index_waveform = sample_index.tolist().index(True) - break -for time in sample_waveform[0].index: - if time >= tstop: - sample_index = sample_waveform[0].index == time - stop_index_waveform = sample_index.tolist().index(True) - break - -original_data_zoom = original_data_value[start_index_original_data:stop_index_original_data] -sampled_data_zoom = sample_waveform[0].values[start_index_waveform:stop_index_waveform] * scale_data -sampled_time_zoom = sample_waveform[0].index[start_index_waveform:stop_index_waveform] * scale_time - -fig, ax = plt.subplots() -ax.plot(sampled_time_zoom, sampled_data_zoom, "r*") -ax.plot(np.array(list(original_data_zoom.index.values)), original_data_zoom.values) -ax.set_title('WaveAfterProbe') -ax.set_xlabel(original_data.units_sweeps["Time"]) -ax.set_ylabel(original_data.units_data[plot_name]) -plt.show() - -############################################################################### -# Plot Slicer Scatter -# ~~~~~~~~~~~~~~~~~~~ -# Create the plot from a start time to stop time in seconds - -fig, ax2 = plt.subplots() -ax2.plot(sample_waveform[0].index, sample_waveform[0].values, "r*") -ax2.set_title('Slicer Scatter: WaveAfterProbe') -ax2.set_xlabel("s") -ax2.set_ylabel("V") -plt.show() - -############################################################################### -# Plot scatter histogram -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create the plot from a start time to stop time in seconds. - -fig, ax4 = plt.subplots() -ax4.set_title('Slicer Histogram: WaveAfterProbe') -ax4.hist(sample_waveform[0].values, orientation='horizontal') -ax4.set_ylabel("V") -ax4.grid() -plt.show() - -############################################################################### -# Get Transient report -# ~~~~~~~~~~~~~~~~~~~~ -# Get Transient report data - -plot_name = "V(b_input_43.int_ami_rx.eye_probe.out)" -cir.solution_type = "NexximTransient" -original_data = cir.post.get_solution_data(expressions=plot_name, - domain="Time", - setup_sweep_name="NexximTransient", - variations=cir.available_variations.nominal) - -############################################################################### -# 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 -waveform_unit = original_data.units_data[plot_name] -waveform_sweep_unit = original_data.units_sweeps["Time"] -tics = np.arange(20e-9, 100e-9, 1e-10, dtype=float) - -sample_waveform = cir.post.sample_waveform( - waveform_data=original_data_value, - waveform_sweep=original_data_sweep, - waveform_unit=waveform_unit, - waveform_sweep_unit=waveform_sweep_unit, - unit_interval=unit_interval, - clock_tics=tics, - pandas_enabled=False, -) - -############################################################################### -# 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 = ansys.aedt.core.constants.unit_converter(1, unit_system="Time", input_units="s", - output_units=waveform_sweep_unit) -scale_data = ansys.aedt.core.constants.unit_converter(1, unit_system="Voltage", input_units="V", - output_units=waveform_unit) - -tstop_ns = scale_time * tstop -tstart_ns = scale_time * tstart - -for time in original_data_sweep: - if tstart_ns <= time: - start_index_original_data = original_data_sweep.index(time) - break -for time in original_data_sweep[start_index_original_data:]: - if time >= tstop_ns: - stop_index_original_data = original_data_sweep.index(time) - break -cont = 0 -for frame in sample_waveform: - if tstart <= frame[0]: - start_index_waveform = cont - break - cont += 1 -for frame in sample_waveform[start_index_waveform:]: - if frame[0] >= tstop: - stop_index_waveform = cont - break - cont += 1 - -original_data_zoom = original_data_value[start_index_original_data:stop_index_original_data] -original_sweep_zoom = original_data_sweep[start_index_original_data:stop_index_original_data] -original_data_zoom_array = np.array(list(map(list, zip(original_sweep_zoom, original_data_zoom)))) -original_data_zoom_array[:, 0] *= 1 -sampled_data_zoom_array = np.array(sample_waveform[start_index_waveform:stop_index_waveform]) -sampled_data_zoom_array[:, 0] *= scale_time -sampled_data_zoom_array[:, 1] *= scale_data - -fig, ax = plt.subplots() -ax.plot(sampled_data_zoom_array[:, 0], sampled_data_zoom_array[:, 1], "r*") -ax.plot(original_sweep_zoom, original_data_zoom_array[:, 1]) -ax.set_title(plot_name) -ax.set_xlabel(waveform_sweep_unit) -ax.set_ylabel(waveform_unit) -plt.show() - -############################################################################### -# Plot slicer scatter -# ~~~~~~~~~~~~~~~~~~~ -# Create the plot from a start time to stop time in seconds. - -sample_waveform_array = np.array(sample_waveform) -fig, ax2 = plt.subplots() -ax2.plot(sample_waveform_array[:, 0], sample_waveform_array[:, 1], "r*") -ax2.set_title('Slicer Scatter: ' + plot_name) -ax2.set_xlabel("s") -ax2.set_ylabel("V") -plt.show() - -############################################################################### -# 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() diff --git a/examples/07-Circuit/Circuit_Example.py b/examples/07-Circuit/Circuit_Example.py deleted file mode 100644 index 9ea3b8e4aaa..00000000000 --- a/examples/07-Circuit/Circuit_Example.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -# sphinx_gallery_thumbnail_path = 'Resources/circuit.png' - -import ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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. The :class:`ansys.aedt.core.Desktop` class initializes AEDT and -# starts the specified version in the specified mode. - -desktop = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, new_thread) -aedt_app = ansys.aedt.core.Circuit(project=ansys.aedt.core.generate_unique_project_name()) -aedt_app.modeler.schematic.schematic_units = "mil" -############################################################################### -# Create circuit setup -# ~~~~~~~~~~~~~~~~~~~~ -# Create and customize an LNA (linear network analysis) 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. - -inductor = aedt_app.modeler.schematic.create_inductor(name="L1", value=1e-9, location=[0, 0]) -resistor = aedt_app.modeler.schematic.create_resistor(name="R1", value=50, location=[500, 0]) -capacitor = aedt_app.modeler.schematic.create_capacitor(name="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] ) -gnd = aedt_app.modeler.components.create_gnd(location=[1200, -100]) - -############################################################################### -# Connect components -# ~~~~~~~~~~~~~~~~~~ -# Connect components with wires. - -port.pins[0].connect_to_component(assignment=inductor.pins[0], use_wire=True) -inductor.pins[1].connect_to_component(assignment=resistor.pins[1], use_wire=True) -resistor.pins[0].connect_to_component(assignment=capacitor.pins[0], use_wire=True) -capacitor.pins[1].connect_to_component(assignment=gnd.pins[0], use_wire=True) - -############################################################################### -# Create transient setup -# ~~~~~~~~~~~~~~~~~~~~~~ -# Create a transient setup. - -setup2 = aedt_app.create_setup(name="MyTransient", setup_type=aedt_app.SETUPS.NexximTransient) -setup2.props["TransientData"] = ["0.01ns", "200ns"] -setup3 = aedt_app.create_setup(name="MyDC", setup_type=aedt_app.SETUPS.NexximDC) - -############################################################################### -# 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. - -solutions = aedt_app.post.get_solution_data(expressions=aedt_app.get_traces_for_plot(category="S")) -solutions.enable_pandas_output = True -real, imag = solutions.full_matrix_real_imag -print(real) - -############################################################################### -# Plot data -# ~~~~~~~~~ -# Create a plot based on solution data. - -fig = solutions.plot() - -############################################################################### -# Close AEDT -# ~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.force_close_desktop` method. -# All methods provide for saving the project before closing. - -desktop.release_desktop() diff --git a/examples/07-Circuit/Circuit_Siwave_Multizones.py b/examples/07-Circuit/Circuit_Siwave_Multizones.py deleted file mode 100644 index 8f9387ae690..00000000000 --- a/examples/07-Circuit/Circuit_Siwave_Multizones.py +++ /dev/null @@ -1,108 +0,0 @@ -""" -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 ansys.aedt.core import Edb, Circuit -import os.path -import ansys.aedt.core - -############################################################################### -# Download file -# ~~~~~~~~~~~~~ -# Download the AEDB file and copy it in the temporary folder. - -temp_folder = ansys.aedt.core.generate_unique_folder_name() -edb_file = ansys.aedt.core.downloads.download_file(destination=temp_folder, directory="edb/siwave_multi_zones.aedb") -working_directory = os.path.join(temp_folder, "workdir") -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") -print(edb_file) - - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -##################################################################################### -# Ground net -# ~~~~~~~~~~ -# Common reference net used across all sub-designs, Mandatory for this work flow. - -common_reference_net = "GND" - -######################################################################################## -# 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=aedt_version, edbpath=edb_file) - -############################################################################### -# Project zones -# ~~~~~~~~~~~~~ -# Copy project zone into sub project. - -edb_zones = edb.copy_zones(working_directory=working_directory) - -############################################################################### -# 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 -# ~~~~~~~ -# Create circuit design, import all sub-project as EM model and connect all corresponding pins in circuit. - -circuit = Circuit(version=aedt_version, project=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. -circuit_setup= circuit.create_setup("Pyedt_LNA") - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~ -# Analyze all siwave projects and solves the circuit. -circuit.analyze() - -############################################################################### -# Define differential pairs -# ~~~~~~~~~~~~~~~~~~~~~~~~~ -circuit.set_differential_pair(assignment="U0.via_38.B2B_SIGP", reference="U0.via_39.B2B_SIGN", differential_mode="U0") -circuit.set_differential_pair(assignment="U1.via_32.B2B_SIGP", reference="U1.via_33.B2B_SIGN", differential_mode="U1") - -############################################################################### -# 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 diff --git a/examples/07-Circuit/Circuit_Subcircuit_Example.py b/examples/07-Circuit/Circuit_Subcircuit_Example.py deleted file mode 100644 index a06fa063381..00000000000 --- a/examples/07-Circuit/Circuit_Subcircuit_Example.py +++ /dev/null @@ -1,76 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################## -# 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 2023 R2 in graphical mode with Circuit. - -circuit = ansys.aedt.core.Circuit(project=ansys.aedt.core.generate_unique_project_name(), - version=aedt_version, - non_graphical=non_graphical, - new_desktop=True - ) -circuit.modeler.schematic_units = "mil" - -############################################################################### -# 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. - -subcircuit = circuit.modeler.schematic.create_subcircuit(location=[0.0, 0.0]) -subcircuit_name = subcircuit.composed_name -circuit.push_down(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. - -circuit.variable_manager.set_variable(name="R_val", expression="35ohm") -circuit.variable_manager.set_variable(name="L_val", expression="1e-7H") -circuit.variable_manager.set_variable(name="C_val", expression="5e-10F") -p1 = circuit.modeler.schematic.create_interface_port(name="In") -r1 = circuit.modeler.schematic.create_resistor(value="R_val") -l1 = circuit.modeler.schematic.create_inductor(value="L_val") -c1 = circuit.modeler.schematic.create_capacitor(value="C_val") -p2 = circuit.modeler.schematic.create_interface_port(name="Out") -circuit.modeler.schematic.connect_components_in_series(assignment=[p1, r1, l1, c1, p2], use_wire=True) -circuit.pop_up() - - -############################################################################### -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT. - -circuit.release_desktop(True, True) diff --git a/examples/07-Circuit/Circuit_Transient.py b/examples/07-Circuit/Circuit_Transient.py deleted file mode 100644 index eec35728cb6..00000000000 --- a/examples/07-Circuit/Circuit_Transient.py +++ /dev/null @@ -1,183 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 2023 R2 in graphical mode with Circuit. - -cir = ansys.aedt.core.Circuit(project=ansys.aedt.core.generate_unique_project_name(), - version=aedt_version, - new_desktop=True, - non_graphical=non_graphical - ) - -############################################################################### -# 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 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 a resistor and ground in the schematic. - -res = cir.modeler.components.create_resistor(name="R1", value="1Meg") -gnd1 = cir.modeler.components.create_gnd() - -############################################################################### -# 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 a probe and rename it to ``Vout``. - -pr1 = cir.modeler.components.components_catalog["Probes:VPROBE"].place("vout") -pr1.parameters["Name"] = "Vout" -pr1.pins[0].connect_to_component(res.pins[0]) -pr2 = cir.modeler.components.components_catalog["Probes:VPROBE"].place("Vin") -pr2.parameters["Name"] = "Vin" -pr2.pins[0].connect_to_component(ibs.pins[0]) - -############################################################################### -# Create setup and analyze -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a transient analysis setup and analyze it. - -trans_setup = cir.create_setup(name="TransientRun", setup_type="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. - -report = cir.post.create_report("V(Vout)", domain="Time") -if not non_graphical: - report.add_cartesian_y_marker(0) -solutions = cir.post.get_solution_data(domain="Time") -solutions.plot("V(Vout)") - -############################################################################### -# Create report inside 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. - -new_report = cir.post.reports_by_category.standard("V(Vout)") -new_report.domain = "Time" -new_report.create() -if not non_graphical: - new_report.add_limit_line_from_points([60, 80], [1, 1], "ns", "V") - vout = new_report.traces[0] - vout.set_trace_properties(style=vout.LINESTYLE.Dot, width=2, trace_type=vout.TRACETYPE.Continuous, - color=(0, 0, 255)) - vout.set_symbol_properties(style=vout.SYMBOLSTYLE.Circle, fill=True, color=(255, 255, 0)) - ll = new_report.limit_lines[0] - ll.set_line_properties(style=ll.LINESTYLE.Solid, width=4, hatch_above=True, violation_emphasis=True, hatch_pixels=2, - color=(0, 0, 255)) -new_report.time_start = "20ns" -new_report.time_stop = "100ns" -new_report.create() -sol = new_report.get_solution_data() -sol.plot() - -############################################################################### -# Create eye diagram inside AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create an eye diagram inside AEDT using the ``new_eye`` object. - -new_eye = cir.post.reports_by_category.eye_diagram("V(Vout)") -new_eye.unit_interval = "1e-9s" -new_eye.time_stop = "100ns" -new_eye.create() - -############################################################################### -# Create eye diagram outside AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create the same eye diagram outside AEDT using Matplotlib and the -# ``get_solution_data`` method. - -unit_interval = 1 -offset = 0.25 -tstop = 200 -tstart = 0 -t_steps = [] -i = tstart + offset -while i < tstop: - i += 2 * unit_interval - t_steps.append(i) - -t = [[i for i in solutions.intrinsics["Time"] if k - 2 * unit_interval < i <= k] for k in - t_steps] -ys = [[i / 1000 for i, j in zip(solutions.data_real(), solutions.intrinsics["Time"]) if - k - 2 * unit_interval < j <= k] for k in t_steps] -fig, ax = plt.subplots(sharex=True) -cellst = np.array([]) -cellsv = np.array([]) -for a, b in zip(t, ys): - an = np.array(a) - an = an - an.mean() - bn = np.array(b) - cellst = np.append(cellst, an) - cellsv = np.append(cellsv, bn) -plt.plot(cellst.T, cellsv.T, zorder=0) -plt.show() - -############################################################################### -# Release AEDT -# ~~~~~~~~~~~~ -# Release AEDT. -cir.save_project() -cir.release_desktop() diff --git a/examples/07-Circuit/Create_Netlist.py b/examples/07-Circuit/Create_Netlist.py deleted file mode 100644 index b63607f7ef5..00000000000 --- a/examples/07-Circuit/Create_Netlist.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -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 and set paths. - -import os - -import ansys.aedt.core - -netlist = ansys.aedt.core.downloads.download_netlist() - -project_name = ansys.aedt.core.generate_unique_project_name() -print(project_name) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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. - -non_graphical = False -NewThread = True - -############################################################################### -# Launch AEDT with Circuit -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT with Circuit. The :class:`ansys.aedt.core.Desktop` class initializes AEDT -# and starts it on the specified version in the specified graphical mode. - -desktop = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, NewThread) -aedtapp = ansys.aedt.core.Circuit(project=project_name) - -############################################################################### -# Define variable -# ~~~~~~~~~~~~~~~ -# Define a design variable by using a ``$`` prefix. - -aedtapp["Voltage"] = "5" - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# After adding any other desired functionalities, close the project and release -# AEDT. - -desktop.release_desktop() 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 deleted file mode 100644 index 15fbe039666..00000000000 --- a/examples/07-Circuit/Reports.py +++ /dev/null @@ -1,134 +0,0 @@ -""" -Circuit: automatic report creation ----------------------------------- -This example shows how you can use PyAEDT to create reports automatically using a JSON file. -""" - -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports and set the local path to the path for PyAEDT. - -import os -from IPython.display import Image -import ansys.aedt.core - -# Set local path to path for PyAEDT -temp_folder = ansys.aedt.core.generate_unique_folder_name() -project_path = ansys.aedt.core.downloads.download_custom_reports(destination=temp_folder) - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -########################################################## -# 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 -NewThread = True - -############################################################################### -# Launch AEDT with Circuit -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Launch AEDT with Circuit. The :class:`ansys.aedt.core.Desktop` class initializes AEDT -# and starts the specified version in the specified mode. - -cir = ansys.aedt.core.Circuit(project=os.path.join(project_path, 'CISPR25_Radiated_Emissions_Example23R1.aedtz'), - non_graphical=non_graphical, - version=aedt_version, - new_desktop=True - ) -cir.analyze() - -############################################################################### -# 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 -# notes and edit axes, the grid, and the legend. You can create custom reports -# in non-graphical mode in AEDT 2023 R2 and later. - -report1 = cir.post.create_report_from_configuration(os.path.join(project_path, 'Spectrum_CISPR_Basic.json')) -out = cir.post.export_report_to_jpg(cir.working_directory, report1.plot_name) -Image(out) - -############################################################################### -# 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 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 = ansys.aedt.core.general_methods.read_json(os.path.join(project_path, 'Transient_CISPR_Custom.json')) - -report2 = cir.post.create_report_from_configuration(report_settings=props, solution_name="NexximTransient") -out = cir.post.export_report_to_jpg(cir.working_directory, report2.plot_name) -Image(out) - -############################################################################### -# Create transient report -# ~~~~~~~~~~~~~~~~~~~~~~~ -# You can customize any aspect of the property dictionary and easily create a new report. -# The following code customizes the curve name. -# The expressions key can be a list of expressions as follows or a dictionary containing the expressions to plot and line properties. -# props["expressions"] = { "V(Battery)" : -# {"color": [0, 255, 0], "trace_style": "Solid", "width": 1, "trace_type": "Continuous"}} - - -props["expressions"] = ["V(Battery)", "V(U1_VDD)"] -props["plot_name"] = "Battery Voltage" -report3 = cir.post.create_report_from_configuration(report_settings=props, solution_name="NexximTransient") -out = cir.post.export_report_to_jpg(cir.working_directory, report3.plot_name) -Image(out) - -############################################################################### -# 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. - -report4 = cir.post.create_report_from_configuration(os.path.join(project_path, 'EyeDiagram_CISPR_Basic.json')) -out = cir.post.export_report_to_jpg(cir.working_directory, report4.plot_name) -Image(out) - -############################################################################### -# Create eye diagram -# ~~~~~~~~~~~~~~~~~~ -# You can create custom reports in -# non-graphical mode in AEDT 2023 R2 and later. - -report4_full = cir.post.create_report_from_configuration(os.path.join(project_path, 'EyeDiagram_CISPR_Custom.json')) - -out = cir.post.export_report_to_jpg(cir.working_directory, report4_full.plot_name) -Image(out) -################################################ -# This is how the spectrum looks like -# .. image:: Resources/spectrum_plot.png - -############################################################################### -# 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() diff --git a/examples/07-Circuit/Touchstone_Management.py b/examples/07-Circuit/Touchstone_Management.py deleted file mode 100644 index bfabb7f8a73..00000000000 --- a/examples/07-Circuit/Touchstone_Management.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -Circuit: Touchstone file management ------------------------------------ -This example shows how you can use objects in a Touchstone file without opening AEDT. - -To provide the advanced postprocessing features needed for this example, Matplotlib and NumPy -must be installed on your machine. - -This example runs only on Windows using CPython. -""" -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports and set the local path to the path for PyAEDT. - -from ansys.aedt.core import downloads - -example_path = downloads.download_touchstone() - -############################################################################### -# Import libraries and Touchstone file -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Import Matplotlib, NumPy, and the Touchstone file. - -from ansys.aedt.core.post.touchstone_parser import read_touchstone - -############################################################################### -# Read Touchstone file -# ~~~~~~~~~~~~~~~~~~~~ -# Read the Touchstone file. - -data = read_touchstone(example_path) - -############################################################################### -# 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. - -worst_rl, global_mean = data.get_worst_curve( - freq_min=1, freq_max=20, worst_is_higher=True, curve_list=data.get_return_loss_index() -) -worst_il, mean2 = data.get_worst_curve(freq_min=1, - freq_max=20, - worst_is_higher=False, - curve_list=data.get_insertion_loss_index() - ) -worst_fext, mean3 = data.get_worst_curve(freq_min=1, - freq_max=20, - worst_is_higher=True, - curve_list=data.get_fext_xtalk_index_from_prefix(tx_prefix="U1", - rx_prefix="U7") - ) -worst_next, mean4 = data.get_worst_curve( - freq_min=1, freq_max=20, worst_is_higher=True, curve_list=data.get_next_xtalk_index("U1") -) diff --git a/examples/07-Circuit/Virtual_Compliance.py b/examples/07-Circuit/Virtual_Compliance.py deleted file mode 100644 index 47d8b9c669b..00000000000 --- a/examples/07-Circuit/Virtual_Compliance.py +++ /dev/null @@ -1,217 +0,0 @@ -""" -Circuit: PCIE virtual compliance --------------------------------- -This example shows how to generate a compliance report in PyAEDT using -the ``VirtualCompliance`` class. -""" - -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports and set paths. - -import os.path -import ansys.aedt.core -from ansys.aedt.core.visualization.post.compliance import VirtualCompliance - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 = True -new_thread = True - -############################################################################### -# Download example files -# ~~~~~~~~~~~~~~~~~~~~~~ -# Download the project and files needed to run the example. -workdir = ansys.aedt.core.downloads.download_file('pcie_compliance') - -projectdir = os.path.join(workdir, "project") - -############################################################################### -# Launch AEDT -# ~~~~~~~~~~~ -# Launch AEDT. - -d = ansys.aedt.core.Desktop(aedt_version, new_desktop=new_thread, non_graphical=non_graphical) - -############################################################################### -# Open and solve layout -# ~~~~~~~~~~~~~~~~~~~~~ -# Open the HFSS 3D Layout project and analyze it using the SIwave solver. -# Before solving, this code ensures that the model is solved from DC to 70GHz and that -# causality and passivity are enforced. - -h3d = ansys.aedt.core.Hfss3dLayout(os.path.join(projectdir, "PCIE_GEN5_only_layout.aedtz"), version=242) -h3d.remove_all_unused_definitions() -h3d.edit_cosim_options(simulate_missing_solution=False) -h3d.setups[0].sweeps[0].props["EnforcePassivity"] = True -h3d.setups[0].sweeps[0].props["Sweeps"]["Data"] = 'LIN 0MHz 70GHz 0.1GHz' -h3d.setups[0].sweeps[0].props["EnforceCausality"] = True -h3d.setups[0].sweeps[0].update() -h3d.analyze() -h3d = ansys.aedt.core.Hfss3dLayout(version=242) -touchstone_path = h3d.export_touchstone() - -############################################################################### -# Create LNA project -# ~~~~~~~~~~~~~~~~~~ -# Use the LNA setup to retrieve Touchstone files -# and generate frequency domain reports. - -cir = ansys.aedt.core.Circuit(project=h3d.project_name, design="Touchstone") -status, diff_pairs, comm_pairs = cir.create_lna_schematic_from_snp(input_file=touchstone_path, start_frequency=0, - stop_frequency=70, auto_assign_diff_pairs=True, - separation=".", pattern=["component", "pin", "net"], - analyze=True) - -insertion = cir.get_all_insertion_loss_list(drivers=diff_pairs, receivers=diff_pairs, drivers_prefix_name="X1", - receivers_prefix_name="U1", math_formula="dB", - nets=["RX0", "RX1", "RX2", "RX3"]) -return_diff = cir.get_all_return_loss_list(excitations=diff_pairs, excitation_name_prefix="X1", math_formula="dB", - nets=["RX0", "RX1", "RX2", "RX3"]) -return_comm = cir.get_all_return_loss_list(excitations=comm_pairs, excitation_name_prefix="COMMON_X1", - math_formula="dB", nets=["RX0", "RX1", "RX2", "RX3"]) -############################################################################### -# Create TDR project -# ~~~~~~~~~~~~~~~~~~ -# Create a TDR project to compute transient simulation and retrieve -# the TDR measurement on a differential pair. -# The original circuit schematic is duplicated and modified to achieve this target. - -result, tdr_probe_name = cir.create_tdr_schematic_from_snp(input_file=touchstone_path, - tx_schematic_pins=["X1.A2.PCIe_Gen4_RX0_P"], - tx_schematic_differential_pins=["X1.A3.PCIe_Gen4_RX0_N"], - termination_pins=["U1.AP26.PCIe_Gen4_RX0_P", - "U1.AN26.PCIe_Gen4_RX0_N"], - differential=True, rise_time=35, use_convolution=True, - analyze=True, design_name="TDR") - -############################################################################### -# Create AMI project -# ~~~~~~~~~~~~~~~~~~ -# Create an Ibis AMI project to compute an eye diagram simulation and retrieve -# eye mask violations. -result, eye_curve_tx, eye_curve_rx = cir.create_ami_schematic_from_snp(input_file=touchstone_path, - ibis_tx_file=os.path.join(projectdir, "models", - "pcieg5_32gt.ibs"), - tx_buffer_name="1p", rx_buffer_name="2p", - tx_schematic_pins=[ - "U1.AM25.PCIe_Gen4_TX0_CAP_P"], - rx_schematic_pins=[ - "X1.B2.PCIe_Gen4_TX0_P"], - tx_schematic_differential_pins=[ - "U1.AL25.PCIe_Gen4_TX0_CAP_N"], - rx_schematic_differentialial_pins=[ - "X1.B3.PCIe_Gen4_TX0_N"], - ibis_tx_component_name="Spec_Model", - use_ibis_buffer=False, differential=True, - bit_pattern="random_bit_count=2.5e3 random_seed=1", - unit_interval="31.25ps", use_convolution=True, - analyze=True, design_name="AMI") - -cir.save_project() - -############################################################################### -# Create virtual compliance report -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Initialize the ``VirtualCompliance`` class -# and set up the main project information needed to generate the report. -# -# -# .. image:: ../../_static/virtual_compliance_class.png -# :width: 400 -# :alt: Virtual compliance class description. -# -# -# .. image:: ../../_static/virtual_compliance_configs.png -# :width: 400 -# :alt: Virtual compliance configuration files hierarchy. -# -# - -template = os.path.join(workdir, "pcie_gen5_templates", "main.json") - -v = VirtualCompliance(cir.desktop_class, str(template)) - -############################################################################### -# Customize project and design -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define the path to the project file and the -# design names to be used in each report generation. -# -# -# .. image:: ../../_static/virtual_compliance_usage.png -# :width: 400 -# :alt: Virtual compliance configuration usage example. -# -# - -v.project_file = cir.project_file -v.reports["insertion losses"].design_name = "LNA" -v.reports["return losses"].design_name = "LNA" -v.reports["common mode return losses"].design_name = "LNA" -v.reports["tdr from circuit"].design_name = "TDR" -v.reports["eye1"].design_name = "AMI" -v.reports["eye3"].design_name = "AMI" -v.parameters["erl"].design_name = "LNA" -v.specs_folder = os.path.join(workdir, 'readme_pictures') - -############################################################################### -# Define trace names -# ~~~~~~~~~~~~~~~~~~ -# Change the trace name with projects and users. -# Reuse the compliance template and update traces accordingly. - - -v.reports["insertion losses"].traces = insertion - -v.reports["return losses"].traces = return_diff - -v.reports["common mode return losses"].traces = return_comm - -v.reports["eye1"].traces = eye_curve_tx -v.reports["eye3"].traces = eye_curve_tx -v.reports["tdr from circuit"].traces = tdr_probe_name -v.parameters = {} -v.parameters["erl"].trace_pins = [ - ["X1.A5.PCIe_Gen4_RX1_P", "X1.A6.PCIe_Gen4_RX1_N", "U1.AR25.PCIe_Gen4_RX1_P", "U1.AP25.PCIe_Gen4_RX1_N"], - [7, 8, 18, 17]] - -############################################################################### -# Generate PDF report -# ~~~~~~~~~~~~~~~~~~~~ -# Generate the reports and produce a PDF report. -# -# -# .. image:: ../../_static/virtual_compliance_scattering1.png -# :width: 400 -# :alt: Insertion loss output. -# -# -# .. image:: ../../_static/virtual_compliance_scattering2.png -# :width: 400 -# :alt: Return loss output. -# -# -# .. image:: ../../_static/virtual_compliance_eye.png -# :width: 400 -# :alt: Eye diagram example. -# -# - -v.create_compliance_report() - -d.release_desktop(True, True) diff --git a/examples/07-EMIT/ComputeInterferenceType.py b/examples/07-EMIT/ComputeInterferenceType.py deleted file mode 100644 index 81608d52a40..00000000000 --- a/examples/07-EMIT/ComputeInterferenceType.py +++ /dev/null @@ -1,201 +0,0 @@ -""" -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. -""" -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. -import sys -from ansys.aedt.core.emit_core.emit_constants import InterfererType, ResultType, TxRxMode -from ansys.aedt.core import Emit -import ansys.aedt.core -import os -import ansys.aedt.core.generic.constants as consts -import subprocess - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -# 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 plotly library (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: - 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 for if emit version is compatible -if aedt_version <= "2023.1": - print("Warning: this example requires AEDT 2023.2 or later.") - sys.exit() - -############################################################################### -# 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 = ansys.aedt.core.launch_desktop(aedt_version, non_graphical=non_graphical, new_desktop=new_thread) - -path_to_desktop_project = ansys.aedt.core.downloads.download_file("emit", "interference.aedtz") -emitapp = Emit(non_graphical=False, new_desktop=False, project=path_to_desktop_project) - -# Get all the radios in the project -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Get lists of all transmitters and receivers in the project. -rev = emitapp.results.analyze() -tx_interferer = InterfererType().TRANSMITTERS -rx_radios = rev.get_receiver_names() -tx_radios = rev.get_interferer_names(tx_interferer) -domain = emitapp.results.interaction_domain() - -if tx_radios is None or rx_radios is None: - print("No receivers or transmitters are in the design.") - sys.exit() - -############################################################################### -# 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. - -power_matrix = [] -all_colors = [] -all_colors, power_matrix = rev.interference_type_classification(domain, use_filter=False, filter_list=[]) - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.force_close_desktop` method. -# All methods provide for saving the project before closing. - -emitapp.save_project() -emitapp.release_desktop() - - -############################################################################### -# 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. - -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 - used for the scenario matrix view are based on the interference type.""" - - all_colors = [] - for color in colors: - col = [] - for cell in color: - col.append(table_colors[cell]) - all_colors.append(col) - - fig = go.Figure(data=[go.Table( - header=dict( - values=['Tx/Rx', '{}'.format(tx_radios[0]), '{}'.format(tx_radios[1])], - line_color='darkslategray', - fill_color='grey', - align=['left', 'center'], - font=dict(color='white', size=16) - ), - cells=dict( - values=[ - rx_radios, - emis[0], - emis[1]], - line_color='darkslategray', - fill_color=['white', all_colors[0], all_colors[1]], - align=['left', 'center'], - height=25, - font=dict( - color=['darkslategray', 'black'], - size=15) - ) - )]) - fig.update_layout( - title=dict( - text='Interference Type Classification', - font=dict(color='darkslategray', size=20), - x=0.5 - ), - width=600 - ) - fig.show() - - -############################################################################### -# Generate a legend -# ~~~~~~~~~~~~~~~~~ -# Define the interference types and colors used to display the results of -# the analysis. - -def create_legend_table(): - """Create a table showing the interference types.""" - classifications = ['In-band/In-band', 'Out-of-band/In-band', - 'In-band/Out-of-band', 'Out-of-band/Out-of-band'] - fig = go.Figure(data=[go.Table( - header=dict( - values=['Interference Type (Source/Victim)'], - line_color='darkslategray', - fill_color=header_color, - align=['center'], - font=dict(color='white', size=16) - ), - cells=dict( - values=[classifications], - line_color='darkslategray', - fill_color=[[table_colors['red'], table_colors['orange'], table_colors['yellow'], table_colors['green']]], - align=['center'], - height=25, - font=dict( - color=['darkslategray', 'black'], - size=15) - ) - )]) - fig.update_layout( - title=dict( - text='Interference Type Classification', - font=dict(color='darkslategray', size=20), - x=0.5 - ), - 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() diff --git a/examples/07-EMIT/ComputeProtectionLevels.py b/examples/07-EMIT/ComputeProtectionLevels.py deleted file mode 100644 index fcfb58ef368..00000000000 --- a/examples/07-EMIT/ComputeProtectionLevels.py +++ /dev/null @@ -1,266 +0,0 @@ -""" -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. -# -# sphinx_gallery_thumbnail_path = "Resources/emit_protection_levels.png" -import os -import sys -import subprocess -import ansys.aedt.core -from ansys.aedt.core import Emit -from ansys.aedt.core.emit_core.emit_constants import TxRxMode, ResultType, InterfererType - -# 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 any missing libraries -required_packages = ['plotly'] -for package in required_packages: - if package not in installed_packages: - install(package) - -# Import required modules -import plotly.graph_objects as go - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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``. -# The ``new_thread`` Boolean variable defines whether to create a new instance -# of AEDT or try to connect to existing instance of it if one is available. - -non_graphical = False -new_thread = True - -############################################################################### -# 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. - -if aedt_version <= "2023.1": - print("Warning: this example requires AEDT 2023.2 or later.") - sys.exit() - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, new_thread) -emitapp = Emit(ansys.aedt.core.generate_unique_project_name()) - -############################################################################### -# 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. -# Exceeding the overload threshold severely densensitizes the receiver. -# Exceeding the intermod threshold can drive the victim receiver into non- -# linear operation, where it operates as a mixer. -# 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 -intermod_threshold = -30 -desense_threshold = -104 - -protection_levels = [damage_threshold, overload_threshold, intermod_threshold, desense_threshold] - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~ -# 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. - """ - if gps.name == radio_name: - radio = gps - elif bluetooth.name == radio_name: - radio = bluetooth - else: - radio = wifi - return radio - -bands = gps.bands() -for band in bands: - for child in band.children: - if "L2 P(Y)" in band.node_name: - band.enabled=True - else: - band.enabled=False - -############################################################################### -# Load the results set -# ~~~~~~~~~~~~~~~~~~~~ -# Create a results revision and load it for analysis. - -rev = emitapp.results.analyze() - -############################################################################### -# Generate a legend -# ~~~~~~~~~~~~~~~~~ -# Define the thresholds and colors used to display the results of -# the protection level analysis. - -def create_legend_table(): - """Create a table showing the defined protection levels.""" - protectionLevels = ['>{} dBm'.format(damage_threshold), '>{} dBm'.format(overload_threshold), - '>{} dBm'.format(intermod_threshold), '>{} dBm'.format(desense_threshold)] - fig = go.Figure(data=[go.Table( - header=dict( - values=['Interference','Power Level Threshold'], - line_color='darkslategray', - fill_color=header_color, - align=['left','center'], - font=dict(color='white',size=16) - ), - cells=dict( - values=[['Damage','Overload','Intermodulation','Clear'], protectionLevels], - line_color='darkslategray', - fill_color=['white',['red','orange','yellow','green']], - align = ['left', 'center'], - font = dict( - color = ['darkslategray','black'], - size = 15) - ) - )]) - fig.update_layout( - title=dict( - text='Protection Levels (dBm)', - font=dict(color='darkslategray',size=20), - x = 0.5 - ), - width = 600 - ) - fig.show() - -############################################################################### -# 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 -# protection level thresholds defined. - -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 - used for the scenario matrix view are based on the highest - protection level that the received power exceeds.""" - fig = go.Figure(data=[go.Table( - header=dict( - values=['Tx/Rx','{}'.format(tx_radios[0]),'{}'.format(tx_radios[1])], - line_color='darkslategray', - fill_color=header_color, - align=['left','center'], - font=dict(color='white',size=16) - ), - cells=dict( - values=[ - rx_radios, - emis[0], - emis[1]], - line_color='darkslategray', - fill_color=['white',colors[0], colors[1]], - align = ['left', 'center'], - font = dict( - color = ['darkslategray','black'], - size = 15) - ) - )]) - fig.update_layout( - title=dict( - text='Protection Levels (dBm)', - font=dict(color='darkslategray',size=20), - x = 0.5 - ), - width = 600 - ) - fig.show() - -############################################################################### -# 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 -# ~~~~~~~~~~~~~~~~~~~~ -# 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=[] - - all_colors, power_matrix = rev.protection_level_classification(domain, global_levels = protection_levels) - - # Create a scenario matrix-like view for the protection levels - create_scenario_view(power_matrix, all_colors, tx_radios, rx_radios) - - # Create a legend for the protection levels - create_legend_table() - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.Desktop.force_close_desktop` method. -# All methods provide for saving the project before closing. - -emitapp.save_project() -emitapp.release_desktop(close_projects=True, close_desktop=True) diff --git a/examples/07-EMIT/EMIT_Example.py b/examples/07-EMIT/EMIT_Example.py deleted file mode 100644 index cd70777db69..00000000000 --- a/examples/07-EMIT/EMIT_Example.py +++ /dev/null @@ -1,95 +0,0 @@ -""" -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. -# -# sphinx_gallery_thumbnail_path = "Resources/emit_simple_cosite.png" - -import os -import ansys.aedt.core -from ansys.aedt.core.emit_core.emit_constants import TxRxMode, ResultType - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 -# of AEDT or try to connect to existing instance of it if one is available. - -non_graphical = False -NewThread = True - -############################################################################### -# 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. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, NewThread) -aedtapp = ansys.aedt.core.Emit(ansys.aedt.core.generate_unique_project_name()) - - -############################################################################### -# Create and connect EMIT components -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Create three radios and connect an antenna to each one. - -rad1 = aedtapp.modeler.components.create_component("New Radio") -ant1 = aedtapp.modeler.components.create_component("Antenna") -if rad1 and ant1: - ant1.move_and_connect_to(rad1) - -# Convenience method to create a radio and antenna connected together -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. - - -############################################################################### -# Run EMIT simulation -# ~~~~~~~~~~~~~~~~~~~ -# Run the EMIT simulation. -# -# This part of the example requires Ansys AEDT 2023 R2. - -if aedt_version > "2023.1" and os.getenv("PYAEDT_DOC_GENERATION", "False") != "1": - rev = aedtapp.results.analyze() - rx_bands = rev.get_band_names(rad2.name, TxRxMode.RX) - tx_bands = rev.get_band_names(rad3.name, TxRxMode.TX) - domain = aedtapp.results.interaction_domain() - domain.set_receiver(rad2.name, rx_bands[0], -1) - domain.set_interferer(rad3.name,tx_bands[0]) - interaction = rev.run(domain) - worst = interaction.get_worst_instance(ResultType.EMI) - if worst.has_valid_values(): - emi = worst.get_value(ResultType.EMI) - print("Worst case interference is: {} dB".format(emi)) - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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) diff --git a/examples/07-EMIT/EMIT_HFSS_Example.py b/examples/07-EMIT/EMIT_HFSS_Example.py deleted file mode 100644 index ecf63b7c92e..00000000000 --- a/examples/07-EMIT/EMIT_HFSS_Example.py +++ /dev/null @@ -1,145 +0,0 @@ -""" -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. -# -# sphinx_gallery_thumbnail_path = "Resources/emit_hfss.png" - -import os - -# Import required modules -import ansys.aedt.core -from ansys.aedt.core.generic.filesystem import Scratch -from ansys.aedt.core.emit_core.emit_constants import TxRxMode, ResultType - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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 -scratch_path = ansys.aedt.core.generate_unique_folder_name() - -############################################################################### -# 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. - -d = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, NewThread) - -temp_folder = os.path.join(scratch_path, ("EmitHFSSExample")) -if not os.path.exists(temp_folder): - os.mkdir(temp_folder) - -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" - -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 = ansys.aedt.core.Emit(my_project) - -############################################################################### -# 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 the RF systems. - -for link in aedtapp.couplings.linkable_design_names: - aedtapp.couplings.add_link(link) - -for link in aedtapp.couplings.coupling_names: - aedtapp.couplings.update_link(link) - -############################################################################### -# Run EMIT simulation -# ~~~~~~~~~~~~~~~~~~~ -# Run the EMIT simulation. -# -# This part of the example requires Ansys AEDT 2023 R2. - -if aedt_version > "2023.1": - rev = aedtapp.results.analyze() - rx_bands = rev.get_band_names(rad1.name, TxRxMode.RX) - tx_bands = rev.get_band_names(rad2.name, TxRxMode.TX) - domain = aedtapp.results.interaction_domain() - domain.set_receiver(rad1.name, rx_bands[0], -1) - domain.set_interferer(rad2.name,tx_bands[0]) - interaction = rev.run(domain) - worst = interaction.get_worst_instance(ResultType.EMI) - if worst.has_valid_values(): - emi = worst.get_value(ResultType.EMI) - print("Worst case interference is: {} dB".format(emi)) - -############################################################################### -# Save project and close AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# After the simulation completes, you can close AEDT or release it using the -# :func:`ansys.aedt.core.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) diff --git a/examples/07-EMIT/Readme.txt b/examples/07-EMIT/Readme.txt deleted file mode 100644 index 35b36f1cd11..00000000000 --- a/examples/07-EMIT/Readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -EMIT examples -~~~~~~~~~~~~~ -These examples use PyAEDT to show some end-to-end workflows for EMIT. -This includes schematic generation, setup, and postprocessing. - diff --git a/examples/07-EMIT/interference_gui.py b/examples/07-EMIT/interference_gui.py deleted file mode 100644 index c47efd4d88d..00000000000 --- a/examples/07-EMIT/interference_gui.py +++ /dev/null @@ -1,621 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import sys -from ansys.aedt.core.emit_core.emit_constants import InterfererType, ResultType, TxRxMode -from ansys.aedt.core import Emit -from ansys.aedt.core import get_pyaedt_app -import ansys.aedt.core -import os -import subprocess -import ansys.aedt.core.generic.constants as consts - -# Check that emit is a compatible version -aedt_version = "2024.2" -if aedt_version < "2023.2": - print("Must have v2023.2 or later") - sys.exit() - -# 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 -desktop = ansys.aedt.core.launch_desktop(aedt_version, non_graphical, new_thread) - -# Add emitapi to system path -emit_path = os.path.join(desktop.install_path, "Delcross") -sys.path.insert(0,emit_path) -import EmitApiPython -api = EmitApiPython.EmitApi() - -# Define .ui file for GUI -ui_file = ansys.aedt.core.downloads.download_file("emit", "interference_gui.ui") -Ui_MainWindow, _ = QtUiTools.loadUiType(ui_file) - -class DoubleDelegate(QtWidgets.QStyledItemDelegate): - def __init__(self, decimals, values, max_power, min_power): - super().__init__() - self.decimals = decimals - self.values = values - self.max_power = max_power - self.min_power = min_power - - def createEditor(self, parent, option, index): - editor = super().createEditor(parent, option, index) - if isinstance(editor, QtWidgets.QLineEdit): - validator = QtGui.QDoubleValidator(parent) - num_rows = len(self.values) - cur_row = index.row() - if cur_row == 0: - min_val = self.values[1] - max_val = self.max_power - elif cur_row == num_rows - 1: - min_val = self.min_power - max_val = self.values[cur_row-1] - else: - min_val = self.values[cur_row + 1] - max_val = self.values[cur_row - 1] - validator.setRange(min_val, max_val, self.decimals) - validator.setNotation(QtGui.QDoubleValidator.Notation.StandardNotation) - editor.setValidator(validator) - return editor - - def update_values(self, values): - self.values = values - -class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): - def __init__(self): - super(MainWindow, self).__init__() - self.emitapp = None - self.populating_dropdown = False - 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): - # 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") - self.desensitization_check = self.findChild(QtWidgets.QCheckBox, "desensitization_check") - self.protection_export_btn = self.findChild(QtWidgets.QPushButton, "protection_export_btn") - 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() - myFont.setBold(True) - 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) - self.protection_save_img_btn.setEnabled(False) - self.file_select_btn.clicked.connect(self.open_file_dialog) - self.protection_export_btn.clicked.connect(self.save_results_excel) - self.protection_results_btn.clicked.connect(self.protection_results) - self.protection_legend_table.resizeRowsToContents() - self.protection_legend_table.resizeColumnsToContents() - self.damage_check.stateChanged.connect(self.protection_results) - self.overload_check.stateChanged.connect(self.protection_results) - self.intermodulation_check.stateChanged.connect(self.protection_results) - self.desensitization_check.stateChanged.connect(self.protection_results) - self.protection_legend_table.setEditTriggers(QtWidgets.QTableWidget.DoubleClicked) - self.global_protection_level = True - 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.changing = False - 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") - self.out_out_check = self.findChild(QtWidgets.QCheckBox, "out_out_check") - self.interference_export_btn = self.findChild(QtWidgets.QPushButton, "interference_export_btn") - self.interference_save_img_btn = self.findChild(QtWidgets.QPushButton, 'interference_save_img_btn') - - # Setup for interference type buttons and table - self.interference_results_btn.setEnabled(False) - self.interference_export_btn.setEnabled(False) - self.interference_save_img_btn.setEnabled(False) - self.interference_export_btn.clicked.connect(self.save_results_excel) - self.interference_results_btn.clicked.connect(self.interference_results) - self.interference_legend_table.resizeRowsToContents() - self.interference_legend_table.resizeColumnsToContents() - self.in_in_check.stateChanged.connect(self.interference_results) - self.in_out_check.stateChanged.connect(self.interference_results) - self.out_in_check.stateChanged.connect(self.interference_results) - 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'], - "orange": [QtGui.QColor(255, 99, 97), '#ff6361'], - "red": [QtGui.QColor(255, 166, 0), '#ffa600'], - "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. - - 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("") - msg = QtWidgets.QMessageBox() - msg.setWindowTitle("Error: Project missing designs.") - msg.setText( - "The selected project has no designs. Projects must have at least " - "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() - msg.setWindowTitle("Error: Project already open") - msg.setText("Project is locked. Close or remove the lock before proceeding. See AEDT log for more information.") - x = msg.exec() - return - - # Populate design dropdown with all design names - designs = desktop_proj.design_list - emit_designs = [] - self.populating_dropdown = True - self.design_name_dropdown.clear() - self.populating_dropdown = False - for d in designs: - 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 - self.warning_label.setHidden(True) - if len(emit_designs) == 0: - 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() - self.radio_dropdown.setEnabled(False) - 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 - - def design_dropdown_changed(self): - if self.populating_dropdown: - # don't load design's on initial project load - return - design_name = self.design_name_dropdown.currentText() - self.emitapp = get_pyaedt_app(self.emitapp.project_name, design_name) - # 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) - - # 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. - - def radio_specific(self): - self.radio_dropdown.setEnabled(self.radio_specific_levels.isChecked()) - self.radio_dropdown.clear() - if self.radio_dropdown.isEnabled(): - self.emitapp.set_active_design(self.design_name_dropdown.currentText()) - radios = self.emitapp.modeler.components.get_radios() - values = [float(self.protection_legend_table.item(row, 0).text()) for row in range(self.protection_legend_table.rowCount())] - for radio in radios: - if radios[radio].has_rx_channels(): - self.protection_levels[radio] = values - self.radio_dropdown.addItem(radio) - else: - self.radio_dropdown.clear() - 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. - - def radio_dropdown_changed(self): - if self.radio_dropdown.isEnabled(): - self.changing = True - for row in range(self.protection_legend_table.rowCount()): - item = self.protection_legend_table.item(row, 0) - item.setText(str(self.protection_levels[self.radio_dropdown.currentText()][row])) - self.changing = False - # update the validator so min/max for each row is properly set - values = [float(self.protection_legend_table.item(row, 0).text()) for row in - 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. - - def table_changed(self): - if self.changing == False: - values = [float(self.protection_legend_table.item(row, 0).text()) for row in - range(self.protection_legend_table.rowCount())] - if self.radio_dropdown.currentText() == '': - index = 'Global' - else: - index = self.radio_dropdown.currentText() - 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. - - def save_image(self): - if self.tab_widget.currentIndex() == 0: - table = self.protection_matrix - else: - table = self.interference_matrix - - fname, _filter = QtWidgets.QFileDialog.getSaveFileName(self, "Save Scenario Matrix", "Scenario Matrix", "png (*.png)") - if fname: - image = QtGui.QImage(table.size(), QtGui.QImage.Format_ARGB32) - table.render(image) - image.save(fname) - - ############################################################################### - # Save scenario matrix to Excel file - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Write the scenario matrix results to an Excel file with color coding. - - def save_results_excel(self): - defaultName = "" - if self.tab_widget.currentIndex() == 0: - table = self.protection_matrix - defaultName = "Protection Level Classification" - else: - table = self.interference_matrix - defaultName = "Interference Type Classification" - - fname, _filter = QtWidgets.QFileDialog.getSaveFileName(self, "Save Scenario Matrix", defaultName, "xlsx (*.xlsx)") - - if fname: - workbook = openpyxl.Workbook() - worksheet = workbook.active - header = self.tx_radios[:] - header.insert(0, "Tx/Rx") - worksheet.append(header) - for row in range(2, table.rowCount()+2): - worksheet.cell(row = row, column = 1, value = str(self.rx_radios[row-2])) - for col in range(2, table.columnCount()+2): - text = str(table.item(row-2, col-2).text()) - worksheet.cell(row = row, column = col, value = text) - cell = worksheet.cell(row, col) - cell.fill = PatternFill(start_color = self.color_dict[self.all_colors[col-2][row-2]][1][1:], - end_color = self.color_dict[self.all_colors[col-2][row-2]][1][1:], - fill_type = "solid") - workbook.save(fname) - - ############################################################################### - # Run interference type simulation - # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - # Run interference type simulation and classify results. - - def interference_results(self): - # Initialize filter check marks and expected filter results - self.interference_checks = [self.in_in_check.isChecked(), self.out_in_check.isChecked(), - self.in_out_check.isChecked(), self.out_out_check.isChecked()] - - self.interference_filters =["TxFundamental:In-band", ["TxHarmonic/Spurious:In-band","Intermod:In-band", "Broadband:In-band"], - "TxFundamental:Out-of-band", ["TxHarmonic/Spurious:Out-of-band","Intermod:Out-of-band", "Broadband:Out-of-band"]] - - # Create list of problem types to analyze according to inputted filters - filter = [i for (i,v) in zip(self.interference_filters, self.interference_checks) if v] - - if self.file_path_box.text() != "" and self.design_name_dropdown.currentText() != "": - if self.previous_design != self.design_name_dropdown.currentText() or self.previous_project != self.file_path_box.text(): - self.previous_design = self.design_name_dropdown.currentText() - self.previous_project = self.file_path_box.text() - self.emitapp.set_active_design(self.design_name_dropdown.currentText()) - - # Check if file is read-only - if self.emitapp.save_project() == False: - msg = QtWidgets.QMessageBox() - msg.setWindowTitle("Writing Error") - msg.setText("An error occurred while writing to the file. Is it readonly? Disk full? See AEDT log for more information.") - x = msg.exec() - return - - # Get results and radios - self.rev = self.emitapp.results.analyze() - self.tx_interferer = InterfererType().TRANSMITTERS - self.rx_radios = self.rev.get_receiver_names() - self.tx_radios = self.rev.get_interferer_names(self.tx_interferer) - - # Check if design is valid - 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. - domain = self.emitapp.results.interaction_domain() - self.all_colors, self.power_matrix = self.rev.interference_type_classification(domain, use_filter = True, filter_list = filter) - - # Save project and plot results on table widget - self.emitapp.save_project() - self.populate_table() - - ############################################################################### - # 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 - self.protection_checks = [self.damage_check.isChecked(), self.overload_check.isChecked(), - self.intermodulation_check.isChecked(), self.desensitization_check.isChecked()] - - self.protection_filters = ['damage', 'overload', 'intermodulation', 'desensitization'] - - filter = [i for (i,v) in zip(self.protection_filters, self.protection_checks) if v] - - if self.file_path_box.text() != "" and self.design_name_dropdown.currentText() != "": - if self.previous_design != self.design_name_dropdown.currentText() or self.previous_project != self.file_path_box.text(): - self.previous_design = self.design_name_dropdown.currentText() - self.previous_project = self.file_path_box.text() - self.emitapp.set_active_design(self.design_name_dropdown.currentText()) - - # Check if file is read-only - if self.emitapp.save_project() == False: - msg = QtWidgets.QMessageBox() - msg.setWindowTitle("Writing Error") - msg.setText("An error occurred while writing to the file. Is it readonly? Disk full? See AEDT log for more information.") - x = msg.exec() - return - - # Get results and design radios - self.tx_interferer = InterfererType().TRANSMITTERS - self.rev = self.emitapp.results.analyze() - self.rx_radios = self.rev.get_receiver_names() - self.tx_radios = self.rev.get_interferer_names(self.tx_interferer) - - # Check if there are radios in the design - if self.tx_radios is None or self.rx_radios is None: - return - - domain = self.emitapp.results.interaction_domain() - self.all_colors, self.power_matrix = self.rev.protection_level_classification(domain, - self.global_protection_level, - self.protection_levels['Global'], - self.protection_levels, use_filter = True, - 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. - - def populate_table(self): - if self.tab_widget.currentIndex() == 0: - table = self.protection_matrix - button = self.protection_export_btn - img_btn = self.protection_save_img_btn - else: - table = self.interference_matrix - button = self.interference_export_btn - img_btn = self.interference_save_img_btn - - num_cols = len(self.all_colors) - num_rows = len(self.all_colors[0]) - table.setColumnCount(num_cols) - table.setRowCount(num_rows) - table.setVerticalHeaderLabels(self.rx_radios) - table.setHorizontalHeaderLabels(self.tx_radios) - - for col in range(num_cols): - for row in range(num_rows): - item = QtWidgets.QTableWidgetItem(str(self.power_matrix[col][row])) - table.setItem(row, col, item) - cell = table.item(row, col) - cell.setBackground(self.color_dict[self.all_colors[col][row]][0]) - - button.setEnabled(True) - img_btn.setEnabled(True) - - def clear_table(self): - # get the table/buttons based on current tab - if self.tab_widget.currentIndex() == 0: - table = self.protection_matrix - button = self.protection_export_btn - img_btn = self.protection_save_img_btn - else: - table = self.interference_matrix - button = self.interference_export_btn - img_btn = self.interference_save_img_btn - - # disable export options - button.setEnabled(False) - img_btn.setEnabled(False) - - # clear the table - table.setColumnCount(0) - table.setRowCount(0) - - ############################################################################### - # GUI closing event - # ~~~~~~~~~~~~~~~~~ - # Close AEDT if the GUI is closed. - def closeEvent(self, event): - msg = QtWidgets.QMessageBox() - msg.setWindowTitle("Closing GUI") - msg.setText("Closing AEDT. Wait for the GUI to close on its own.") - x = msg.exec() - if self.emitapp: - self.emitapp.close_project() - self.emitapp.close_desktop() - else: - desktop.release_desktop(True, True) - -############################################################################### -# Run GUI -# ~~~~~~~ -# Launch the GUI. If you want to run the GUI, uncomment the ``window.show()`` and -# ``app.exec_()`` method calls. - -if __name__ == '__main__' and os.getenv("PYAEDT_DOC_GENERATION", "False") != "1": - app = QtWidgets.QApplication([]) - window = MainWindow() - window.show() - app.exec() -else: - desktop.release_desktop(True, True) 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 9e6dcec59fc..00000000000 --- a/examples/07-TwinBuilder/01-RC_Circuit_Example.py +++ /dev/null @@ -1,112 +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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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. - -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 = ansys.aedt.core.TwinBuilder(project=ansys.aedt.core.generate_unique_project_name(), - version=aedt_version, - non_graphical=non_graphical, - new_desktop=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], x_label="Time", y_label="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 deleted file mode 100644 index 08e5a5e8608..00000000000 --- a/examples/07-TwinBuilder/02-Wiring_A_Rectifier.py +++ /dev/null @@ -1,153 +0,0 @@ -""" -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 ansys.aedt.core - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Select version and set launch options -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Select the Twin Builder version and set the launch options. The following code -# launches Twin Builder 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. - -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 = ansys.aedt.core.TwinBuilder(project=ansys.aedt.core.generate_unique_project_name(), - version=aedt_version, - non_graphical=non_graphical, - new_desktop=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. - -G = 0.00254 - -# Create an AC sinosoidal source component. - -source = tb.modeler.schematic.create_voltage_source("V_AC", "ESINE", 100, 50, [-1 * G, 0]) - -# Create the four diodes of the bridge rectifier. - -diode1 = tb.modeler.schematic.create_diode(location=[10 * G, 6 * G], angle=270) -diode2 = tb.modeler.schematic.create_diode(location=[20 * G, 6 * G], angle=270) -diode3 = tb.modeler.schematic.create_diode(location=[10 * G, -4 * G], angle=270) -diode4 = tb.modeler.schematic.create_diode(location=[20 * G, -4 * G], angle=270) - -# Create a capacitor filter. - -capacitor = tb.modeler.schematic.create_capacitor(value=1e-6, location=[29 * G, -10 * G]) - -# Create a load resistor. - -resistor = tb.modeler.schematic.create_resistor(value=100000, location=[39 * G, -10 * G]) - -# Create a ground. - -gnd = tb.modeler.components.create_gnd(location=[5 * G, -16 * G]) - -############################################################################### -# Connect components -# ~~~~~~~~~~~~~~~~~~ -# Connect components with wires. - -# Wire the diode bridge. - -tb.modeler.schematic.create_wire(points=[diode1.pins[0].location, diode3.pins[0].location]) -tb.modeler.schematic.create_wire(points=[diode2.pins[1].location, diode4.pins[1].location]) -tb.modeler.schematic.create_wire(points=[diode1.pins[1].location, diode2.pins[0].location]) -tb.modeler.schematic.create_wire(points=[diode3.pins[1].location, diode4.pins[0].location]) - -# Wire the AC source. - -tb.modeler.schematic.create_wire(points=[source.pins[1].location, [0, 10 * G], [15 * G, 10 * G], [15 * G, 5 * G]]) -tb.modeler.schematic.create_wire(points=[source.pins[0].location, [0, -10 * G], [15 * G, -10 * G], [15 * G, -5 * G]]) - -# Wire the filter capacitor and load resistor. - -tb.modeler.schematic.create_wire(points=[resistor.pins[0].location, [40 * G, 0], [22 * G, 0]]) -tb.modeler.schematic.create_wire(points=[capacitor.pins[0].location, [30 * G, 0]]) - -# Wire the ground. - -tb.modeler.schematic.create_wire(points=[resistor.pins[1].location, [40 * G, -15 * G], gnd.pins[0].location]) -tb.modeler.schematic.create_wire(points=[capacitor.pins[1].location, [30 * G, -15 * G]]) -tb.modeler.schematic.create_wire(points=[gnd.pins[0].location, [5 * G, 0], [8 * G, 0]]) - -# Zoom to fit the schematic -tb.modeler.zoom_to_fit() - -############################################################################### -# Parametrize transient setup -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Parametrize the default transient setup by setting the end time. - -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 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 = "R1.V" -x = tb.post.get_solution_data(R_Value, "TR", "Time") -plt.plot(x.intrinsics["Time"], x.data_real(R_Value)) - -plt.grid() -plt.xlabel("Time") -plt.ylabel("AC to DC Conversion using Rectifier") -plt.show() - -############################################################################### -# 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() diff --git a/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py b/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py deleted file mode 100644 index 13d1dd2b527..00000000000 --- a/examples/07-TwinBuilder/03-Dynamic_ROM_Creation_And_Visualization.py +++ /dev/null @@ -1,184 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import os -import shutil -import matplotlib.pyplot as plt -from ansys.aedt.core import TwinBuilder -from ansys.aedt.core import generate_unique_project_name -from ansys.aedt.core.generic.general_methods import generate_unique_folder_name -from ansys.aedt.core import downloads -from ansys.aedt.core.generic.settings import settings - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# Select version and set launch options -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Select the Twin Builder version and set launch options. The following code -# launches Twin Builder 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. - -non_graphical = False -new_thread = True - -############################################################################### -# Set up input data -# ~~~~~~~~~~~~~~~~~ -# Define needed file name - -source_snapshot_data_zipfilename = "Ex1_Mechanical_DynamicRom.zip" -source_build_conf_file = "dynarom_build.conf" - -# Download data from example_data repository -temp_folder = generate_unique_folder_name() -source_data_folder = downloads.download_twin_builder_data(source_snapshot_data_zipfilename, True, temp_folder) -source_data_folder = downloads.download_twin_builder_data(source_build_conf_file, True, temp_folder) - -# Toggle these for local testing -# source_data_folder = "D:\\Scratch\\TempDyn" - -data_folder = os.path.join(source_data_folder, "Ex03") - -# Unzip training data and config file -downloads.unzip(os.path.join(source_data_folder, source_snapshot_data_zipfilename), data_folder) -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 using an implicit declaration and add a new design with -# a default setup for building the dynamic ROM component. - -tb = TwinBuilder(project=generate_unique_project_name(), - version=aedt_version, - non_graphical=non_graphical, - new_desktop=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". -current_desktop_config = tb._odesktop.GetDesktopConfiguration() -current_schematic_environment = tb._odesktop.GetSchematicEnvironment() -tb._odesktop.SetDesktopConfiguration("Twin Builder") -tb._odesktop.SetSchematicEnvironment(1) - -# Get the dynamic ROM builder object -rom_manager = tb._odesign.GetROMManager() -dynamic_rom_builder = rom_manager.GetDynamicROMBuilder() - -# Build the dynamic ROM with specified configuration file -conf_file_path = os.path.join(data_folder, source_build_conf_file) -dynamic_rom_builder.Build(conf_file_path.replace('\\', '/')) - -# Test if ROM was created successfully -dynamic_rom_path = os.path.join(data_folder, 'DynamicRom.dyn') -if os.path.exists(dynamic_rom_path): - tb._odesign.AddMessage("Info", "path exists: {}".format(dynamic_rom_path.replace('\\', '/')), "") -else: - tb._odesign.AddMessage("Info", "path does not exist: {}".format(dynamic_rom_path), "") - -# Create the ROM component definition in Twin Builder -rom_manager.CreateROMComponent(dynamic_rom_path.replace('\\', '/'), 'dynarom') - -############################################################################### -# Create schematic -# ~~~~~~~~~~~~~~~~ -# Place components to create a schematic. - -# Define the grid distance for ease in calculations - -G = 0.00254 - -# Place a dynamic ROM component - -rom1 = tb.modeler.schematic.create_component("ROM1", "", "dynarom", [36 * G, 28 * G]) - -# Place two excitation sources - -source1 = tb.modeler.schematic.create_periodic_waveform_source(None, "PULSE", 190, 0.002, "300deg", 210, 0, - [20 * G, 29 * G]) -source2 = tb.modeler.schematic.create_periodic_waveform_source(None, "PULSE", 190, 0.002, "300deg", 210, 0, - [20 * G, 25 * G]) - -# Connect components with wires - -tb.modeler.schematic.create_wire([[22 * G, 29 * G], [33 * G, 29 * G]]) -tb.modeler.schematic.create_wire([[22 * G, 25 * G], [30 * G, 25 * G], [30 * G, 28 * G], [33 * G, 28 * G]]) - -# Zoom to fit the schematic -tb.modeler.zoom_to_fit() - -############################################################################### -# 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 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 -# output of the dynamic ROM. - -input_excitation = "PULSE1.VAL" -x = tb.post.get_solution_data(input_excitation, "TR", "Time") -plt.plot(x.intrinsics["Time"], x.data_real(input_excitation)) - -output_temperature = "ROM1.Temperature_history" -x = tb.post.get_solution_data(output_temperature, "TR", "Time") -plt.plot(x.intrinsics["Time"], x.data_real(output_temperature)) - -plt.grid() -plt.xlabel("Time") -plt.ylabel("Temperature History Variation with Input Temperature Pulse") -plt.show() - -############################################################################### -# 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. - -# Clean up the downloaded data -shutil.rmtree(source_data_folder) - -# Restore earlier desktop configuration and schematic environment -tb._odesktop.SetDesktopConfiguration(current_desktop_config) -tb._odesktop.SetSchematicEnvironment(current_schematic_environment) - -tb.release_desktop() diff --git a/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py b/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py deleted file mode 100644 index 1d65667f41c..00000000000 --- a/examples/07-TwinBuilder/04-Static_ROM_Creation_And_Visualization.py +++ /dev/null @@ -1,189 +0,0 @@ -""" -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 -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import os -import math -import shutil -import matplotlib.pyplot as plt -from ansys.aedt.core import TwinBuilder -from ansys.aedt.core import generate_unique_project_name -from ansys.aedt.core.generic.general_methods import generate_unique_folder_name -from ansys.aedt.core import downloads -from ansys.aedt.core.generic.settings import settings - -########################################################## -# Set AEDT version -# ~~~~~~~~~~~~~~~~ -# Set AEDT version. - -aedt_version = "2024.2" - -############################################################################### -# 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. -# -# 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. - -non_graphical = False -new_thread = True - -############################################################################### -# Set up input data -# ~~~~~~~~~~~~~~~~~ -# Define needed file name - -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 -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" - -data_folder = os.path.join(source_data_folder, "Ex04") - -# Unzip training data and config file -downloads.unzip(os.path.join(source_data_folder, source_snapshot_data_zipfilename), data_folder) -shutil.copyfile(os.path.join(source_data_folder, source_build_conf_file), - 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 using an implicit declaration and add a new design with -# a default setup for building the static ROM component. - -tb = TwinBuilder(project=generate_unique_project_name(), version=aedt_version, - non_graphical=non_graphical, new_desktop=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". -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() - -# Build the static ROM with specified configuration file -confpath = os.path.join(data_folder, source_build_conf_file) -static_rom_builder.Build(confpath.replace('\\', '/')) - -# Test if ROM was created successfully -static_rom_path = os.path.join(data_folder, 'StaticRom.rom') -if os.path.exists(static_rom_path): - tb.logger.info("Built intermediate rom file successfully at: %s", static_rom_path) -else: - tb.logger.error("Intermediate rom file not found at: %s", static_rom_path) - -# Create the ROM component definition in Twin Builder -rom_manager.CreateROMComponent(static_rom_path.replace('\\', '/'), 'staticrom') - -############################################################################### -# Create schematic -# ~~~~~~~~~~~~~~~~ -# Place components to create a schematic. - -# Define the grid distance for ease in calculations -G = 0.00254 - -# Place a dynamic ROM component -rom1 = tb.modeler.schematic.create_component("ROM1", "", "staticrom", [40 * G, 25 * G]) - -# 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 - -tb.modeler.schematic.create_wire([[22 * G, 29 * G], [33 * G, 29 * G]]) -tb.modeler.schematic.create_wire([[22 * G, 25 * G], [30 * G, 25 * G], [30 * G, 28 * G], [33 * G, 28 * G]]) - -# Enable storage of views - -rom1.set_property("store_snapshots", 1) -rom1.set_property("view1_storage_period", "10s") -rom1.set_property("view2_storage_period", "10s") - -# Zoom to fit the schematic -tb.modeler.zoom_to_fit() - -############################################################################### -# 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 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 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") - x.plot() - e_value = "ROM1.outfield_mode_2" - x = tb.post.get_solution_data(e_value, "TR", "Time") - x.plot() - e_value = "SINE1.VAL" - x = tb.post.get_solution_data(e_value, "TR", "Time") - x.plot() - e_value = "SINE2.VAL" - x = tb.post.get_solution_data(e_value, "TR", "Time") - x.plot() - - -############################################################################### -# 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. - -# Clean up the downloaded data -shutil.rmtree(source_data_folder) - -# Restore earlier desktop configuration and schematic environment -tb._odesktop.SetDesktopConfiguration(current_desktop_config) -tb._odesktop.SetSchematicEnvironment(current_schematic_environment) - -tb.release_desktop() diff --git a/examples/07-TwinBuilder/Readme.txt b/examples/07-TwinBuilder/Readme.txt deleted file mode 100644 index df697376902..00000000000 --- a/examples/07-TwinBuilder/Readme.txt +++ /dev/null @@ -1,4 +0,0 @@ -Twin Builder examples -~~~~~~~~~~~~~~~~~~~~~ -These examples use PyAEDT to show some end-to-end workflows for Twin Builder. -This includes schematic generation, setup, and postprocessing. diff --git a/examples/08-FilterSolutions/Lumped_Element_Response.py b/examples/08-FilterSolutions/Lumped_Element_Response.py deleted file mode 100644 index 971463f3195..00000000000 --- a/examples/08-FilterSolutions/Lumped_Element_Response.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -Design a lumped element filter ------------------------------- -This example shows how to use PyAEDT to use the ``FilterSolutions`` module to design and -visualize the frequency response of a band-pass Butterworth filter. -""" - -############################################################################### -# Perform required imports -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Perform required imports. - -import ansys.aedt.core -import ansys.aedt.core.filtersolutions_core.attributes -from ansys.aedt.core.filtersolutions_core.attributes import FilterType, FilterClass, FilterImplementation -from ansys.aedt.core.filtersolutions_core.ideal_response import FrequencyResponseColumn -from ansys.aedt.core.filtersolutions_core.export_to_aedt import PartLibraries, ExportFormat -import matplotlib.pyplot as plt - -############################################################################### -# Create the lumped design -# ~~~~~~~~~~~~~~~~~~~~~~~~ -# Create a lumped element filter design and assign the class, type, frequency, and order. -design = ansys.aedt.core.FilterSolutions(version="2025.1", implementation_type= FilterImplementation.LUMPED) -design.attributes.filter_class = FilterClass.BAND_PASS -design.attributes.filter_type = FilterType.BUTTERWORTH -design.attributes.pass_band_center_frequency = "1G" -design.attributes.pass_band_width_frequency = "500M" -design.attributes.filter_order = 5 -############################################################################## -# Plot the frequency response of the filter -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Plot the frequency response of the filter without any transmission zeros. - -freq, mag_db = design.ideal_response.frequency_response(FrequencyResponseColumn.MAGNITUDE_DB) -plt.plot(freq, mag_db, linewidth=2.0, label="Without Tx Zero") -def format_plot(): - plt.xlabel("Frequency (Hz)") - plt.ylabel("Magnitude S21 (dB)") - plt.title("Ideal Frequency Response") - plt.xscale("log") - plt.legend() - plt.grid() -format_plot() -plt.show() - -############################################################################## -# Add a transmission zero to the filter design -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Add a transmission zeros that yields nulls separated by 2 times the pass band width (1 GHz). -# Plot the frequency response of the filter with the transmission zero. - -design.transmission_zeros_ratio.append_row("2.0") -freq_with_zero, mag_db_with_zero = design.ideal_response.frequency_response(FrequencyResponseColumn.MAGNITUDE_DB) -plt.plot(freq, mag_db, linewidth=2.0, label="Without Tx Zero") -plt.plot(freq_with_zero, mag_db_with_zero, linewidth=2.0, label="With Tx Zero") -format_plot() -plt.show() - -############################################################################## -# Generate the netlist for the designed filter -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Generate and print the netlist for the designed filter with the added transmission zero to filter. -netlist = design.topology.circuit_response() -print("Netlist: \n", netlist) diff --git a/examples/Readme.txt b/examples/Readme.txt deleted file mode 100644 index 088894ba498..00000000000 --- a/examples/Readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -.. _ref_example_gallery: - -Examples -======== -End-to-end examples show how you can use PyAEDT. If PyAEDT is installed -on your machine, you can download these examples as Python files or Jupyter -notebooks and run them locally. - -.. note:: - Some examples require additional Python packages. diff --git a/pyproject.toml b/pyproject.toml index 9019d657219..5f1fde6412d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -71,52 +71,21 @@ dotnet = [ "dotnetcore2==3.1.23; platform_system=='Linux'", "pywin32>=303; platform_system=='Windows'", ] + doc = [ "ansys-sphinx-theme>=0.10.0,<1.1", - "ipython>=8.13.0,<8.28", - "joblib>=1.3.0,<1.5", - "jupyterlab>=4.0.0,<4.3", - "matplotlib>=3.5.0,<3.10", - "nbsphinx>=0.9.0,<0.10", "numpydoc>=1.5.0,<1.9", - "openpyxl>=3.0.0,<3.2", - "osmnx>=1.1.0,<1.10", - "pypandoc>=1.10.0,<1.14", - #"pytest-sphinx", - "pyvista[io]>=0.38.0,<0.45", "recommonmark", - "scikit-rf>=0.30.0,<1.4", "Sphinx>=7.1.0,<8.1", # NOTE: latest compatible version for Python 3.8 is 2021.3.14 "sphinx-autobuild==2021.3.14; python_version == '3.8'", "sphinx-autobuild==2024.9.19; python_version > '3.8'", - #"sphinx-autodoc-typehints", "sphinx-copybutton>=0.5.0,<0.6", "sphinx-gallery>=0.14.0,<0.18", - #"sphinx-notfound-page", "sphinx_design>=0.4.0,<0.7", - #"sphinxcontrib-websupport", - "SRTM.py", - "utm", -] -doc-no-examples = [ - "ansys-sphinx-theme>=0.10.0,<1.1", - "numpydoc>=1.5.0,<1.9", - "recommonmark", - "Sphinx>=7.1.0,<8.1", - # NOTE: latest compatible version for Python 3.8 is 2021.3.14 - "sphinx-autobuild==2021.3.14; python_version == '3.8'", - "sphinx-autobuild==2024.9.19; python_version > '3.8'", - #"sphinx-autodoc-typehints", - "sphinx-copybutton>=0.5.0,<0.6", - "sphinx-gallery>=0.14.0,<0.18", - #"sphinx-notfound-page", - #"sphinxcontrib-websupport", - "sphinx_design>=0.4.0,<0.7", - "matplotlib>=3.5.0,<3.10", - "scikit-rf>=0.30.0,<1.4", "pyvista[io]>=0.38.0,<0.45", ] + all = [ "matplotlib>=3.5.0,<3.10", "numpy>=1.20.0,<2",