From a3b3d96012372d89008a7d4c379a33fbf6c2e195 Mon Sep 17 00:00:00 2001 From: svandenb-dev <74993647+svandenb-dev@users.noreply.github.com> Date: Fri, 6 Oct 2023 21:48:30 +0200 Subject: [PATCH] EDB - Load amat material file from Aedt (#3713) * edb intersection bug fix * pyaedt cutout bug fix * load amat material in edb * load amat material in edb * load amat material in edb * load amat material in edb * New methods: add_material_from_aedt which expect an aedt material name load_material_from_amat which load all materials in amat current limitations: supports only materials with float value (no nonlinear materials and no formulas) * Implemented suggestion * Implemented suggestion * Implemented suggestion * Implemented suggestion * added docstring * Update pyaedt/edb_core/materials.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> * Update pyaedt/edb_core/materials.py Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --------- Co-authored-by: maxcapodi78 Co-authored-by: Massimo Capodiferro <77293250+maxcapodi78@users.noreply.github.com> Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- _unittest/test_00_EDB.py | 13 ++ doc/source/Getting_started/Quickcode.rst | 2 +- doc/styles/Vocab/ANSYS/accept.txt | 3 +- ignore_words.txt | 1 + pyaedt/edb_core/materials.py | 162 +++++++++++++++++++++++ pyaedt/edb_core/stackup.py | 5 +- 6 files changed, 183 insertions(+), 3 deletions(-) diff --git a/_unittest/test_00_EDB.py b/_unittest/test_00_EDB.py index 6e77e4ef0ca..e3a864eb78a 100644 --- a/_unittest/test_00_EDB.py +++ b/_unittest/test_00_EDB.py @@ -2855,6 +2855,7 @@ def test_145_arc_data(self): assert self.edbapp.nets["1.2V_DVDDL"].primitives[0].arcs[0].height def test_145_via_volume(self): + # vias = [ via for via in list(self.edbapp.padstacks.padstack_instances.values()) @@ -2903,3 +2904,15 @@ def test_147_find_dc_shorts(self): edbapp.nets["DDR4_DM3"].find_dc_short(True) assert len(edbapp.nets["DDR4_DM3"].find_dc_short()) == 0 edbapp.close() + + def test_148_load_amat(self): + assert "Rogers RO3003 (tm)" in self.edbapp.materials.materials_in_aedt + material_file = os.path.join(self.edbapp.materials.syslib, "Materials.amat") + assert self.edbapp.materials.add_material_from_aedt("Arnold_Magnetics_N28AH_-40C") + assert "Arnold_Magnetics_N28AH_-40C" in self.edbapp.materials.materials.keys() + assert self.edbapp.materials.load_amat(material_file) + material_list = list(self.edbapp.materials.materials.keys()) + assert material_list + assert len(material_list) > 0 + assert self.edbapp.materials.materials["Rogers RO3003 (tm)"].loss_tangent == 0.0013 + assert self.edbapp.materials.materials["Rogers RO3003 (tm)"].permittivity == 3.0 diff --git a/doc/source/Getting_started/Quickcode.rst b/doc/source/Getting_started/Quickcode.rst index 529eb42963d..7c484435191 100644 --- a/doc/source/Getting_started/Quickcode.rst +++ b/doc/source/Getting_started/Quickcode.rst @@ -31,7 +31,7 @@ page on the Ansys Developer portal, you can post questions, share ideas, and get To reach the project support team, email `pyansys.core@ansys.com `_. -Example Workflow +Example workflow ---------------- Here’s a brief example of how PyAEDT works: diff --git a/doc/styles/Vocab/ANSYS/accept.txt b/doc/styles/Vocab/ANSYS/accept.txt index 9110f363fe4..16e7708252b 100644 --- a/doc/styles/Vocab/ANSYS/accept.txt +++ b/doc/styles/Vocab/ANSYS/accept.txt @@ -81,5 +81,6 @@ EDT pyansys Slurm Python.NET - +Toolkits +toolkits diff --git a/ignore_words.txt b/ignore_words.txt index 7e7db77bd34..c8fa792f47c 100644 --- a/ignore_words.txt +++ b/ignore_words.txt @@ -31,3 +31,4 @@ ro aline COM gRPC +Toolkits diff --git a/pyaedt/edb_core/materials.py b/pyaedt/edb_core/materials.py index 5ff95073891..154ef5d5d4b 100644 --- a/pyaedt/edb_core/materials.py +++ b/pyaedt/edb_core/materials.py @@ -1,7 +1,9 @@ from __future__ import absolute_import # noreorder import difflib +import fnmatch import logging +import os import warnings from pyaedt import is_ironpython @@ -365,12 +367,38 @@ def __getitem__(self, item): def __init__(self, pedb): self._pedb = pedb + self._syslib = os.path.join(self._pedb.base_path, "syslib") + self._personal_lib = None + self._materials_in_aedt = None if not self.materials: self.add_material("air") self.add_material("copper", 1, 0.999991, 5.8e7, 0, 0) self.add_material("fr4_epoxy", 4.4, 1, 0, 0.02, 0) self.add_material("solder_mask", 3.1, 1, 0, 0.035, 0) + @property + def materials_in_aedt(self): + """Retrieve the dictionary of materials available in AEDT syslib.""" + if self._materials_in_aedt: + return self._materials_in_aedt + self._materials_in_aedt = self._read_materials() + return self._materials_in_aedt + + @property + def syslib(self): + """Retrieve the project sys library.""" + return self._syslib + + @property + def personallib(self): + """Get or Set the user personallib.""" + return self._personal_lib + + @personallib.setter + def personallib(self, value): + self._personal_lib = value + self._materials_in_aedt = self._read_materials() + @pyaedt_function_handler() def _edb_value(self, value): return self._pedb.edb_value(value) @@ -807,3 +835,137 @@ def get_property_by_material_name(self, property_name, material_name): else: return property_box.ToDouble() return False + + @pyaedt_function_handler() + def add_material_from_aedt(self, material_name): + """Add a material read from ``syslib amat`` library. + + Parameters + ---------- + material_name : str + Material name. + + Returns + ------- + bool + "True`` when successful, ``False`` when failed. + """ + if material_name in self.materials_in_aedt: + if material_name in list(self.materials.keys()): + self._pedb.logger.warning("Material {} already exists. Skipping it.".format(material_name)) + return False + new_material = self.add_material(name=material_name) + material = self.materials_in_aedt[material_name] + try: + new_material.permittivity = float(material["permittivity"]) + except (KeyError, TypeError): + pass + try: + new_material.conductivity = float(material["conductivity"]) + except (KeyError, TypeError): + pass + try: + new_material.mass_density = float(material["mass_density"]) + except (KeyError, TypeError): + pass + try: + new_material.permeability = float(material["permeability"]) + except (KeyError, TypeError): + pass + try: + new_material.loss_tangent = float(material["dielectric_loss_tangent"]) + except (KeyError, TypeError): + pass + try: + new_material.specific_heat = float(material["specific_heat"]) + except (KeyError, TypeError): + pass + try: + new_material.thermal_expansion_coefficient = float(material["thermal_expansion_coeffcient"]) + except (KeyError, TypeError): + pass + return True + + @pyaedt_function_handler() + def load_amat(self, amat_file): + """Load material from an amat file and add materials to Edb. + + Parameters + ---------- + amat_file : str + Full path to the amat file to read and add to the Edb. + """ + material_dict = self._read_materials(amat_file) + for material_name, material in material_dict.items(): + if not material_name in list(self.materials.keys()): + new_material = self.add_material(name=material_name) + try: + new_material.permittivity = float(material["permittivity"]) + except (KeyError, TypeError): + pass + try: + new_material.conductivity = float(material["conductivity"]) + except (KeyError, TypeError): + pass + try: + new_material.mass_density = float(material["mass_density"]) + except (KeyError, TypeError): + pass + try: + new_material.permeability = float(material["permeability"]) + except (KeyError, TypeError): + pass + try: + new_material.loss_tangent = float(material["dielectric_loss_tangent"]) + except (KeyError, TypeError): + pass + try: + new_material.specific_heat = float(material["specific_heat"]) + except (KeyError, TypeError): + pass + try: + new_material.thermal_expansion_coefficient = float(material["thermal_expansion_coeffcient"]) + except (KeyError, TypeError): + pass + return True + + @pyaedt_function_handler() + def _read_materials(self, mat_file=None): + def get_mat_list(file_name, mats): + from pyaedt.generic.LoadAEDTFile import load_entire_aedt_file + + mread = load_entire_aedt_file(file_name) + for mat, mdict in mread.items(): + if mat != "$base_index$": + try: + mats[mat] = mdict["MaterialDef"][mat] + except KeyError: + mats[mat] = mdict + + if mat_file and os.path.exists(mat_file): + materials = {} + get_mat_list(mat_file, materials) + return materials + + amat_sys = [ + os.path.join(dirpath, filename) + for dirpath, _, filenames in os.walk(self.syslib) + for filename in filenames + if fnmatch.fnmatch(filename, "*.amat") + ] + amat_personal = [] + if self.personallib: + amat_personal = [ + os.path.join(dirpath, filename) + for dirpath, _, filenames in os.walk(self.personallib) + for filename in filenames + if fnmatch.fnmatch(filename, "*.amat") + ] + materials = {} + for amat in amat_sys: + get_mat_list(amat, materials) + + if amat_personal: + for amat in amat_personal: + get_mat_list(amat, materials) + return materials diff --git a/pyaedt/edb_core/stackup.py b/pyaedt/edb_core/stackup.py index 4c769a4b5ea..09043aab508 100644 --- a/pyaedt/edb_core/stackup.py +++ b/pyaedt/edb_core/stackup.py @@ -666,7 +666,10 @@ def add_layer( fillMaterial = "fr4_epoxy" if material.lower() not in materials_lower: - logger.error(material + " does not exist in material library") + if material in self._pedb.materials.materials_in_aedt: + self._pedb.materials.add_material_from_aedt("material") + else: + logger.error(material + " does not exist in material library") else: material = materials_lower[material.lower()]