Skip to content

Commit

Permalink
Merge branch 'main' into release/0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
maxcapodi78 authored and maxcapodi78 committed Feb 19, 2022
2 parents 6fbf2a7 + b38a438 commit 05117e7
Show file tree
Hide file tree
Showing 42 changed files with 1,109 additions and 889 deletions.
47 changes: 25 additions & 22 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,24 @@ PyAEDT includes functionality for interacting with the following AEDT tools and
What is PyAEDT?
---------------
PyAEDT is a Python library that interacts directly with the AEDT API
to make scripting simpler for the end user. It uses an architecture
that can be reused for all AEDT 3D products (HFSS, Icepak, Maxwell 3D,
Q3D and Mechanical) as well as 2D tools. It also provides support for circuit tools like
to make scripting simpler for the end user. Its architecture
can be reused for all AEDT 3D products (HFSS, Icepak, Maxwell 3D, and
Q3D), 2D tools, and Ansys Mechanical. It also provides support for circuit tools like
Nexxim and system simulation tools like Twin Builder. Finally it provides scripting
capabilities in Ansys layout tools like HFSS 3D Layout and EDB. Its class and method structures
simplify operation for the end user while reusing information as much as
capabilities in Ansys layout tools like HFSS 3D Layout and EDB. Its class and method
structures simplify operation for the end user while reusing information as much as
possible across the API.

Documentation and Issues
------------------------
See the `API Documentation <https://aedtdocs.pyansys.com/API/>`_ and explore
the `Examples <https://aedtdocs.pyansys.com/examples/index.html>`_.

To post issues, questions, and code, go to `PyAEDT Issues
<https://github.com/pyansys/PyAEDT/issues>`_.
In addition to installation, usage, and contribution information, the PyAEDT
documentation provides `API documentation <https://aedtdocs.pyansys.com/API/>`_,
`examples <https://aedtdocs.pyansys.com/examples/index.html>`_, and `code guidelines
<https://aedtdocs.pyansys.com/Resources/Code_Guidelines.html>`_.

On the `PyAEDT Issues <https://github.com/pyansys/PyAEDT/issues>`_ page, you can
create issues to submit questions, report bugs, and request new features. To reach
the project support team, email `[email protected] <[email protected]>`_.

Dependencies
------------
Expand All @@ -48,10 +50,9 @@ PyAEDT supports AEDT versions 2021 R1 or newer.
Student Version
---------------

PyAEDT now supports also AEDT Student version 2021 R2. Visit
PyAEDT supports AEDT Student version 2021 R2. For more information, see
`Student Version page <https://www.ansys.com/academic/students/ansys-e
lectronics-desktop-student>`_
for more info.
lectronics-desktop-student>`_.


Why PyAEDT?
Expand Down Expand Up @@ -81,23 +82,23 @@ The main advantages of PyAEDT are:

Example Workflow
-----------------
1. Initialize the `Desktop` class with the version of AEDT to use.
1. Initialize the ``Desktop`` class with the version of AEDT to use.
2. Initialize the application to use within AEDT.


Connect to Desktop from Python IDE
----------------------------------
PyAEDT works both inside AEDT and as a standalone application.
It automatically detects whether it is running in an IronPython or CPython
environment and initializes the Desktop accordingly. PyAEDT also provides
advanced error management. Usage examples follow.
environment and initializes AEDT accordingly. PyAEDT also
provides advanced error management. Usage examples follow.

Explicit Desktop Declaration and Error Management
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. code:: python
# Launch AEDT 2021 R1 in Non-Graphical mode
Launch AEDT 2021 R1 in non-graphical mode
from pyaedt import Desktop, Circuit
with Desktop(specified_version="2021.1",
Expand Down Expand Up @@ -130,18 +131,20 @@ Implicit Desktop Declaration and Error Management
Remote Application Call
~~~~~~~~~~~~~~~~~~~~~~~
You can make a remote application call on a CPython server
or any Windows client machine.

On a CPython Server
On a CPython Server:

.. code:: python
Launch Pyaedt remote server on CPython
Launch PyAEDT remote server on CPython
from pyaedt.common_rpc import launch_server
launch_server()
On any Windows client machine
On any Windows client machine:

.. code:: python
Expand Down Expand Up @@ -177,8 +180,8 @@ License
-------
PyAEDT is licensed under the MIT license.

This PyAEDT module makes no commercial claim over Ansys
whatsoever. PyAEDT extends the functionality of AEDT by adding
This module makes no commercial claim over Ansys whatsoever.
PyAEDT extends the functionality of AEDT by adding
an additional Python interface to AEDT without changing the core
behavior or license of the original software. The use of the
interactive control of PyAEDT requires a legally licensed
Expand Down
1 change: 1 addition & 0 deletions _setup_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def recursive_glob(startpath, filepattern):
("dlls", recursive_glob(os.path.join("pyaedt", "dlls"), "*")),
("misc", recursive_glob(os.path.join("pyaedt", "misc"), "*")),
("License", recursive_glob(".", "*.md")),
("xaml", ["pyaedt/generic/wpf_template.xaml"]),
("version", ["pyaedt/version.txt"]),
("setup-distutils", ["setup-distutils.py"]),
]
Expand Down
7 changes: 6 additions & 1 deletion _unittest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@
import gc
import sys
from pyaedt.generic.general_methods import is_ironpython, inside_desktop
from pyaedt import settings

log_path = os.path.join(tempfile.gettempdir(), "test.log")
if os.path.exists(os.path.join(tempfile.gettempdir(), "test.log")):
os.remove(log_path)
settings.logger_file_path = log_path
settings.enable_error_handler = False
if is_ironpython:
import _unittest_ironpython.conf_unittest as pytest
else:
import pytest

os.environ["PYAEDT_ERROR_HANDLER"] = "False"

local_path = os.path.dirname(os.path.realpath(__file__))

Expand Down
22 changes: 13 additions & 9 deletions _unittest/test_00_EDB.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

test_project_name = "Galileo_edb"
bom_example = "bom_example.csv"
from _unittest.conftest import config, desktop_version, local_path, scratch_path, is_ironpython
from _unittest.conftest import config, desktop_version, local_path, scratch_path, is_ironpython, settings

try:
import pytest
Expand Down Expand Up @@ -42,6 +42,10 @@ def test_00_export_ipc2581(self):
self.edbapp.export_to_ipc2581(ipc_path)
assert os.path.exists(ipc_path)

# Export should be made with units set to default -millimeter-.
self.edbapp.export_to_ipc2581(ipc_path, "mm")
assert os.path.exists(ipc_path)

def test_01_find_by_name(self):
comp = self.edbapp.core_components.get_component_by_name("J1")
assert comp is not None
Expand Down Expand Up @@ -334,12 +338,12 @@ def test_40_create_siwave_ac_analsyis(self):
assert self.edbapp.core_siwave.add_siwave_ac_analysis()

def test_41_create_siwave_dc_analsyis(self):
settings = self.edbapp.core_siwave.get_siwave_dc_setup_template()
settings.accuracy_level = 0
settings.use_dc_custom_settings = True
settings.name = "myDCIR_3"
settings.pos_term_to_ground = "I1"
assert self.edbapp.core_siwave.add_siwave_dc_analysis(settings)
settings_dc = self.edbapp.core_siwave.get_siwave_dc_setup_template()
settings_dc.accuracy_level = 0
settings_dc.use_dc_custom_settings = True
settings_dc.name = "myDCIR_3"
settings_dc.pos_term_to_ground = "I1"
assert self.edbapp.core_siwave.add_siwave_dc_analysis(settings_dc)

def test_42_get_nets_from_pin_list(self):
cmp_pinlist = self.edbapp.core_padstack.get_pinlist_from_component_and_net("U2A5", "GND")
Expand Down Expand Up @@ -500,7 +504,7 @@ def test_57_stackup_limits(self):
assert self.edbapp.core_stackup.stackup_limits()

def test_58_create_polygon(self):
os.environ["PYAEDT_ERROR_HANDLER"] = "True"
settings.enable_error_handler = True
points = [[-0.025, -0.02], [0.025, -0.02], [0.025, 0.02], [-0.025, 0.02], [-0.025, -0.02]]
plane = self.edbapp.core_primitives.Shape("polygon", points=points)
points = [
Expand All @@ -526,7 +530,7 @@ def test_58_create_polygon(self):
points = [[0.001, -0.001, "ccn", 0.0, -0.0012]]
plane = self.edbapp.core_primitives.Shape("polygon", points=points)
assert not self.edbapp.core_primitives.create_polygon(plane, "TOP")
os.environ["PYAEDT_ERROR_HANDLER"] = "False"
settings.enable_error_handler = False

def test_59_create_path(self):
points = [
Expand Down
26 changes: 26 additions & 0 deletions _unittest/test_12_PostProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,32 @@ def test_07_export_fields_from_Calculator(self):
)
assert os.path.exists(os.path.join(self.local_scratch.path, "Efield.fld"))

self.aedtapp.post.export_field_file_on_grid(
"Mag_E",
"Setup1 : LastAdaptive",
self.aedtapp.available_variations.nominal_w_values,
os.path.join(self.local_scratch.path, "MagEfieldSph.fld"),
gridtype="Spherical",
grid_stop=[5, 300, 300],
grid_step=[5, 50, 50],
isvector=False,
intrinsics="5GHz",
)
assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldSph.fld"))

self.aedtapp.post.export_field_file_on_grid(
"Mag_E",
"Setup1 : LastAdaptive",
self.aedtapp.available_variations.nominal_w_values,
os.path.join(self.local_scratch.path, "MagEfieldCyl.fld"),
gridtype="Cylindrical",
grid_stop=[5, 300, 5],
grid_step=[5, 50, 5],
isvector=False,
intrinsics="5GHz",
)
assert os.path.exists(os.path.join(self.local_scratch.path, "MagEfieldCyl.fld"))

@pytest.mark.skipif(
config["build_machine"], reason="Skipped because it cannot run on build machine in non-graphical mode"
)
Expand Down
4 changes: 3 additions & 1 deletion _unittest/test_14_AedtLogger.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Import required modules
from pyaedt.aedt_logger import AedtLogger
from pyaedt import Hfss
from pyaedt import Hfss, settings


class TestClass:
Expand Down Expand Up @@ -166,6 +166,7 @@ def test_02_output_file_with_app_filter(self):
@pytest.mark.skipif(is_ironpython, reason="stdout redirection does not work in IronPython.")
def test_03_stdout_with_app_filter(self):
capture = CaptureStdOut()
settings.logger_file_path = ""
with capture:
logger = AedtLogger(to_stdout=True)
logger.info("Info for Global")
Expand Down Expand Up @@ -244,6 +245,7 @@ def test_04_disable_output_file_handler(self):
design_logger.removeHandler(handler)

os.remove(path)
settings.logger_file_path = ""

@pytest.mark.skipif(is_ironpython, reason="stdout redirection does not work in IronPython.")
def test_05_disable_stdout(self):
Expand Down
22 changes: 19 additions & 3 deletions _unittest/test_20_HFSS.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
except ImportError:
import _unittest_ironpython.conf_unittest as pytest
# Setup paths for module imports
from _unittest.conftest import scratch_path, local_path
from _unittest.conftest import scratch_path, local_path, settings
import gc

# Import required modules
Expand Down Expand Up @@ -211,6 +211,22 @@ def test_06c_create_linear_step_sweep(self):
assert sweep.props["RangeEnd"] == str(freq_stop) + units
assert sweep.props["Type"] == "Fast"

# Create a linear step sweep with the incorrect sweep type.
try:
sweep = self.aedtapp.create_linear_step_sweep(
setupname="MySetup",
sweepname="StepFast",
unit=units,
freqstart=freq_start,
freqstop=freq_stop,
step_size=step_size,
sweep_type="Incorrect",
)
except AttributeError as e:
exception_raised = True
assert e.args[0] == "Invalid `sweep_type`. It has to be 'Discrete', 'Interpolating', or 'Fast'."
assert exception_raised

def test_06d_create_single_point_sweep(self):
assert self.aedtapp.create_single_point_sweep(
setupname="MySetup",
Expand All @@ -231,11 +247,11 @@ def test_06d_create_single_point_sweep(self):
assert self.aedtapp.create_single_point_sweep(
setupname="MySetup", unit="GHz", freq=[1.1e1, 1.2e1, 1.3e1], save_single_field=[True, False, True]
)
os.environ["PYAEDT_ERROR_HANDLER"] = "True"
settings.enable_error_handler = True
assert not self.aedtapp.create_single_point_sweep(
setupname="MySetup", unit="GHz", freq=[1, 2e2, 3.4], save_single_field=[True, False]
)
os.environ["PYAEDT_ERROR_HANDLER"] = "False"
settings.enable_error_handler = False

def test_06e_delete_setup(self):
setup_name = "SetupToDelete"
Expand Down
1 change: 1 addition & 0 deletions _unittest/test_21_Circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,4 @@ def test_26_component_catalog(self):
assert isinstance(comp_catalog.find_components("cap"), list)
assert comp_catalog["LISN:CISPR25_LISN"].place("Lisn1")
assert not comp_catalog["Capacitors"]
assert comp_catalog["LISN:CISPR25_LISN"].props
6 changes: 6 additions & 0 deletions _unittest/test_34_TwinBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,9 @@ def test_10_set_hmin(self):

def test_11_set_end_time(self):
assert self.aedtapp.set_end_time("5s")

def test_12_catalog(self):
comp_catalog = self.aedtapp.modeler.components.components_catalog
assert not comp_catalog["Capacitors"]
assert comp_catalog["Aircraft Electrical VHDLAMS\\Basic:lowpass_filter"].props
assert comp_catalog["Aircraft Electrical VHDLAMS\\Basic:lowpass_filter"].place("LP1")
7 changes: 7 additions & 0 deletions _unittest_ironpython/run_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@
import os
import sys
import unittest
import tempfile
from datetime import datetime
from pyaedt import settings

log_path = os.path.join(tempfile.gettempdir(), "test.log")
if os.path.exists(os.path.join(tempfile.gettempdir(), "test.log")):
os.remove(log_path)
settings.logger_file_path = log_path

from pyaedt.generic.general_methods import is_ironpython

Expand Down
7 changes: 4 additions & 3 deletions doc/source/API/Application.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
AEDT Applications
=================
The PyAEDT API includes these classes for applications and modules.
The application has to be initialized by the user. All other classes and methods are inherited into application class.
Desktop application is implicitly launched in any of the other applications.
The PyAEDT API includes classes for applications and modules. You must initialize the
application case. All other classes and methods are inherited into the application class.
The desktop application is implicitly launched in any of the other applications.

Example with Desktop:

.. code:: python
Expand Down
Loading

0 comments on commit 05117e7

Please sign in to comment.