Skip to content

Commit

Permalink
Merge branch 'main' into fieldplot_markers
Browse files Browse the repository at this point in the history
  • Loading branch information
Samuelopez-ansys authored Aug 12, 2024
2 parents 82c1ab4 + f572b8a commit 2054cb8
Show file tree
Hide file tree
Showing 19 changed files with 208 additions and 91 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ body:
description: Run `python --version` to verify your Python version
multiple: false
options:
- '3.7'
- '3.8'
- '3.9'
- '3.10'
- '3.11'
- 'IronPython'
validations:
required: true
Expand Down
6 changes: 2 additions & 4 deletions .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,9 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
target: ['all', 'installer']
exclude:
- python-version: '3.7'
target: 'installer'

steps:
- name: Build wheelhouse and perform smoke test
uses: ansys/actions/build-wheelhouse@v4
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ the API.

## Install on CPython from PyPI

You can install PyAEDT on CPython 3.7 through 3.10 from PyPI with this command:
You can install PyAEDT on CPython 3.8 through 3.12 from PyPI with this command:


```sh
pip install pyaedt
Expand Down
3 changes: 2 additions & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

## 关于 PyAEDT 的安装

1. 您可以使用 `PyPI` 工具将 `PyAEDT` 安装在 `CPython 3.7-3.10` 版本上:
1. 您可以使用 `PyPI` 工具将 `PyAEDT` 安装在 `CPython 3.8-3.12` 版本上:

``` python
pip install pyaedt
```
Expand Down
Binary file added _unittest/example_models/T98/transient_fs.aedtz
Binary file not shown.
4 changes: 4 additions & 0 deletions _unittest/test_28_Maxwell3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,16 @@ def test_32_matrix(self, add_app):
rectangle2 = m3d.modeler.create_rectangle(0, [9, 1.5, 0], [2.5, 5], name="Sheet2")
rectangle3 = m3d.modeler.create_rectangle(0, [16.5, 1.5, 0], [2.5, 5], name="Sheet3")
rectangle4 = m3d.modeler.create_rectangle(0, [32.5, 1.5, 0], [2.5, 5], name="Sheet4")
box1 = m3d.modeler.create_box([0, 0, 0], [10, 10, 5], "MyBox1")
box2 = m3d.modeler.create_box([10, 10, 10], [10, 10, 5], "MyBox2")

m3d.assign_voltage(rectangle1.faces[0], amplitude=1, name="Voltage1")
m3d.assign_voltage("Sheet1", amplitude=1, name="Voltage5")
m3d.assign_voltage(rectangle2.faces[0], amplitude=1, name="Voltage2")
m3d.assign_voltage(rectangle3.faces[0], amplitude=1, name="Voltage3")
m3d.assign_voltage(rectangle4.faces[0], amplitude=1, name="Voltage4")
m3d.assign_voltage(box1.faces, amplitude=1, name="Voltage6")
m3d.assign_voltage(box2, amplitude=1, name="Voltage7")

L = m3d.assign_matrix(assignment="Voltage1")
assert L.props["MatrixEntry"]["MatrixEntry"][0]["Source"] == "Voltage1"
Expand Down
9 changes: 9 additions & 0 deletions _unittest/test_98_Icepak.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
coldplate = "ColdPlateExample_231"
power_budget = "PB_test_231"
native_import = "one_native_component"
transient_fs = "transient_fs"

else:
coldplate = "ColdPlateExample"
Expand Down Expand Up @@ -1801,3 +1802,11 @@ def test_80_global_mesh_region(self):
g_m_r.update()
g_m_r.global_region.object.material_name = "Carbon Monoxide"
assert g_m_r.global_region.object.material_name == "Carbon Monoxide"

def test_81_transient_fs(self, add_app):
app = add_app(application=Icepak, project_name=transient_fs, subfolder=test_subfolder)
fs = app.post.create_field_summary()
for t in ["0s", "1s", "2s", "3s", "4s", "5s"]:
fs.add_calculation("Object", "Surface", "Box1", "Temperature", time=t)
df = fs.get_field_summary_data(pandas_output=True)
assert not df["Mean"].empty
10 changes: 5 additions & 5 deletions doc/source/Getting_started/ClientServer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Client-server
You can launch PyAEDT on a remote machine if these conditions are met:

- AEDT and PyAEDT is installed on client and server machines.
- The same Python version is used on the client and server machines. (CPython 3.7+
- The same Python version is used on the client and server machines. (CPython 3.8+
is embedded in the AEDT installation.)

gRPC connection in AEDT 2022 R2 and later
Expand Down Expand Up @@ -44,15 +44,15 @@ On a CPython Server run the ``pyaedt_service_manager`` service that listens on p
for incoming requests of connections from clients. The port is configurable.
Requirements:

- Python 3.7+ Virtual Environment.
- Python 3.8+ Virtual Environment.
- pyaedt > 0.6.0

On Linux, in addition to the preceding requirements, these environments are needed:
- You can use the CPython version in the AEDT installation folder if you first
add the Python library folder to the ``LD_LIBRARY_PATH`` environment variable.
- You can use the Python 3.7 or later version that is installed.
- You can export ``ANSYSEM_ROOT222=/path/to/AnsysEM/v222/Linux64``.
- You can export ``LD_LIBRARY_PATH=$ANSYSEM_ROOT222/common/mono/Linux64/lib:$ANSYSEM_ROOT222/Delcross:$LD_LIBRARY_PATH``.
- You can use the Python 3.8 or later version that is installed.
- You can export ``ANSYSEM_ROOT242=/path/to/AnsysEM/v242/Linux64``.
- You can export ``LD_LIBRARY_PATH=$ANSYSEM_ROOT242/common/mono/Linux64/lib:$ANSYSEM_ROOT242/Delcross:$LD_LIBRARY_PATH``.

On the server, the ``pyaedt_service_manager`` service listen for incoming connections:

Expand Down
6 changes: 3 additions & 3 deletions doc/source/Resources/pyaedt_installer_from_aedt.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def install_pyaedt():
# run_command(
# '"{}" --default-timeout=1000 install git+https://github.com/ansys/pyaedt.git@main'.format(pip_exe))
if args.version <= "231":
run_command('"{}" --default-timeout=1000 install pyaedt[all]'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install pyaedt[all]=="0.9.3"'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install jupyterlab'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install ipython -U'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install ipyvtklink'.format(pip_exe))
Expand All @@ -222,14 +222,14 @@ def install_pyaedt():
# Extract all contents to a directory. (You can specify a different extraction path if needed.)
zip_ref.extractall(unzipped_path)
if args.version <= "231":
run_command('"{}" install --no-cache-dir --no-index --find-links={} pyaedt[all]'.format(pip_exe,
run_command('"{}" install --no-cache-dir --no-index --find-links={} pyaedt[all]=="0.9.3"'.format(pip_exe,
unzipped_path))
else:
run_command('"{}" install --no-cache-dir --no-index --find-links={} pyaedt[installer]'.format(pip_exe,
unzipped_path))
else:
if args.version <= "231":
run_command('"{}" --default-timeout=1000 install pyaedt[all]'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install pyaedt[all]=="0.9.3"'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install jupyterlab'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install ipython -U'.format(pip_exe))
run_command('"{}" --default-timeout=1000 install ipyvtklink'.format(pip_exe))
Expand Down
10 changes: 5 additions & 5 deletions doc/source/User_guide/postprocessing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To use PyAEDT to create a report in AEDT, you can follow this general structure:
from pyaedt import Hfss
hfss = Hfss()
hfss.analyze_nominal()
hfss.analyze()
hfss.post.create_report(["db(S11)", "db(S12)"])
Expand All @@ -26,7 +26,7 @@ You can also generate reports in Matplotlib:
from pyaedt import Hfss
hfss = Hfss()
hfss.analyze_nominal()
hfss.analyze()
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
Expand All @@ -46,7 +46,7 @@ To access all available category, use the ``reports_by_category`` class.
from pyaedt import Hfss
hfss = Hfss()
hfss.analyze_nominal()
hfss.analyze()
# Create a 3D far field
new_report = hfss.post.reports_by_category.far_field(expressions="db(RealizedGainTotal)",
setup=hfss.nominal_adaptive)
Expand All @@ -58,7 +58,7 @@ You can plot the field plot directly in HFSS and export it to image files.
from pyaedt import Hfss
hfss = Hfss()
hfss.analyze_nominal()
hfss.analyze()
cutlist = ["Global:XY"]
setup_name = hfss.existing_analysis_sweeps[0]
Expand All @@ -82,7 +82,7 @@ PyAEDT leverages PyVista to export and plot fields outside AEDT, generating imag
from pyaedt import Hfss
hfss = Hfss()
hfss.analyze_nominal()
hfss.analyze()
cutlist = ["Global:XY"]
setup_name = hfss.existing_analysis_sweeps[0]
quantity_name = "ComplexMag_E"
Expand Down
5 changes: 5 additions & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ PyAEDT documentation |version|
PyAEDT is a Python client library that interacts directly with the Ansys Electronics Desktop (AEDT) API,
enabling straightforward and efficient automation in your workflow.

.. note:: Expected breaking changes with version `1.0`

If you want to know more about the breaking changes expected
in the incoming version `1.0`, see the :ref:`release_1_0`.

.. note::
Also consider viewing the `PyEDB documentation <https://edb.docs.pyansys.com/version/stable/>`_.
PyEDB is a Python client library for processing complex and large layout designs in the Ansys
Expand Down
79 changes: 79 additions & 0 deletions doc/source/release_1_0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.. _release_1_0:

Breaking changes in release 1.0
===============================

This page describes the breaking changes expected in the upcoming major version 1.0 of PyAEDT.
These changes include the deprecation of certain function argument names and the restructuring
of the codebase.

Deprecation of function argument names
--------------------------------------

In the 1.0 release, several function argument names are deprecated. You should review
your code and check the warnings that are logged at run time.
The following example shows a warning triggered by the use of an argument that is currently acceptable but is not going to work with version 1.0.

.. code-block:: python
from pyaedt import Circuit
c = Circuit(designname="whatever")
Expected log output:

.. code-block:: text
PyAEDT WARNING: Argument `designname` is deprecated for method `__init__`; use `design` instead.
Restructuring of the codebase
-----------------------------

To facilitate the maintenance of PyAEDT and to adhere to PyAnsys' guidelines, the codebase
is being restructured. The sources are to be moved from ``pyaedt`` to ``src.ansys.aedt``
to improve the organization and maintainability of the codebase.

The changes to the structure follow:

.. code-block:: text
Old structure:
--------------
pyaedt/
├── application/
└── ...
New structure:
--------------
src/
└── ansys/
└── aedt/
├── application/
├── ...
When migrating to major release `1.0`, please update any references or imports in your project
accordingly. An example of migration is shown below:

**Old import:**

.. code-block:: python
from pyaedt import Circuit
**New import:**

.. code-block:: python
from ansys.aedt import Circuit
Other changes in release 1.0
============================

In addition to the major changes described earlier, modifications are continuously performed to
improve the quality of the project, its maintainability, its documentation, and
to ensure users' need are met as efficiently as possible. This includes ensuring
consistent argument names, improving data encapsulation, strengthening CI/CD, and extracting
examples to a dedicated project.

For more information on the status of the 1.0 release, see `PyAEDT Milestone <https://github.com/ansys/pyaedt/milestone/3>` .
4 changes: 2 additions & 2 deletions examples/04-Icepak/Sherlock_Example.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,15 +215,15 @@
# Analyze the model
# ~~~~~~~~~~~~~~~~~

ipk.analyze(cores=4, tasks=4)
# ipk.analyze(cores=4, tasks=4)
ipk.save_project()

###############################################################################
# Get solution data and plots
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~

plot1 = ipk.post.create_fieldplot_surface(ipk.modeler["COMP_U10"].faces, "SurfTemperature")
ipk.post.plot_field("SurfPressure", ipk.modeler["COMP_U10"].faces, show=False, export_path=ipk.working_directory)
# ipk.post.plot_field("SurfPressure", ipk.modeler["COMP_U10"].faces, show=False, export_path=ipk.working_directory)


###############################################################################
Expand Down
67 changes: 30 additions & 37 deletions pyaedt/generic/general_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,75 +973,68 @@ def is_project_locked(project_path):


@pyaedt_function_handler()
def is_license_feature_available(feature="electronics_desktop", count=1, input_dir=None): # pragma: no cover
"""Check if license feature is available.
def available_license_feature(
feature="electronics_desktop", input_dir=None, port=1055, name="127.0.0.1"
): # pragma: no cover
"""Check available license feature.
Parameters
----------
feature : str
Feature increment name. The default is the electronics desktop one.
count : int
Number of increments of the same feature available.
Feature increment name. The default is the ``"electronics_desktop"``.
input_dir : str, optional
AEDT installation path. The default is ``None``, in which
case the first identified AEDT installation from :func:`pyaedt.misc.misc.installed_versions` method
is taken.
port : int, optional
Server port number.
name : str, optional
License server name.
Returns
-------
bool
``True`` when feature available, ``False`` when feature not available.
int
Number of available license features, ``False`` when license server is down.
"""
import subprocess # nosec B404

if not input_dir:
input_dir = list(installed_versions().values())[0]

if is_linux:
ansysli_util_path = os.path.join(input_dir, "licensingclient", "linx64", "ansysli_util")
ansysli_util_path = os.path.join(input_dir, "licensingclient", "linx64", "lmutil")
else:
ansysli_util_path = os.path.join(input_dir, "licensingclient", "winx64", "ansysli_util")
ansysli_util_path = os.path.join(input_dir, "licensingclient", "winx64", "lmutil")

my_env = os.environ.copy()

tempfile_status = tempfile.NamedTemporaryFile(suffix=".txt", delete=False).name
tempfile_checkout = tempfile.NamedTemporaryFile(suffix=".txt", delete=False).name

# License server status
cmd = [ansysli_util_path, "-statli"]

f = open(tempfile_status, "w")

subprocess.Popen(cmd, stdout=f, stderr=f, env=my_env).wait() # nosec

f.close()

is_server_down = False
with open_file(tempfile_status, "r") as f:
for line in f:
if line == "ansysli_server process could not be found.\n":
is_server_down = True
break

if is_server_down:
pyaedt_logger.warning("License server process could not be found.")
return False

cmd = [ansysli_util_path, "-checkcount", str(count), "-checkout", feature]
cmd = [ansysli_util_path, "lmstat", "-f", feature, "-c", str(port) + "@" + str(name)]

f = open(tempfile_checkout, "w")

subprocess.Popen(cmd, stdout=f, stderr=f, env=my_env).wait() # nosec

f.close()

checkout_lines = []
available_licenses = 0
pattern_license = r"Total of\s+(\d+)\s+licenses? issued;\s+Total of\s+(\d+)\s+licenses? in use"
pattern_error = r"Error getting status"
with open_file(tempfile_checkout, "r") as f:
for line in f:
checkout_lines.append(line)
if "CHECKOUT FAILED" in checkout_lines[1] or len(checkout_lines) != 2:
pyaedt_logger.warning(checkout_lines[0])
return False
return True
line = line.strip()
match_license = re.search(pattern_license, line)
if match_license:
total_licenses_issued = int(match_license.group(1))
total_licenses_in_use = int(match_license.group(2))
available_licenses = total_licenses_issued - total_licenses_in_use
break
match_error = re.search(pattern_error, line)
if match_error:
pyaedt_logger.error(line)
return False
return available_licenses


@pyaedt_function_handler()
Expand Down
Loading

0 comments on commit 2054cb8

Please sign in to comment.