Source code for squadds.simulations.utils_ansys

from __future__ import annotations

from typing import Any

from ansys.aedt.core import Hfss

from squadds.simulations.utils_geometry import calculate_center_and_dimensions


[docs] def getMeshScreenshot(projectname, designname, solutiontype="Eigenmode"): raise NotImplementedError()
def _cryo_silicon_args(permittivity: float, loss_tangent: float) -> list[Any]: return [ "NAME:silicon", "CoordinateSystemType:=", "Cartesian", "BulkOrSurfaceType:=", 1, [ "NAME:PhysicsTypes", "set:=", ["Electromagnetic", "Thermal", "Structural"], ], [ "NAME:AttachedData", [ "NAME:MatAppearanceData", "property_data:=", "appearance_data", "Red:=", 210, "Green:=", 105, "Blue:=", 30, "Transparency:=", 0, ], ], "permittivity:=", str(permittivity), "permeability:=", "1.0", "conductivity:=", "0", "dielectric_loss_tangent:=", str(loss_tangent), "magnetic_loss_tangent:=", "0", "thermal_conductivity:=", "0.01", "mass_density:=", "0", "specific_heat:=", "0", "thermal_expansion_coefficient:=", "0", "youngs_modulus:=", "0", "poissons_ratio:=", "0", "diffusivity:=", "0.8", "molecular_mass:=", "0", "viscosity:=", "0", ] class _LiveMaterialApp: def __init__(self, source_renderer: Any): live_pinfo = getattr(source_renderer, "pinfo", None) live_project = getattr(live_pinfo, "project", None) live_design = getattr(live_pinfo, "design", None) live_desktop = getattr(live_pinfo, "desktop", None) self._oproject = getattr(live_project, "_project", None) self._odesign = getattr(live_design, "_design", None) self._desktop = getattr(live_desktop, "_desktop", None) if self._desktop is None: self._desktop = getattr(getattr(live_project, "parent", None), "_desktop", None) self.design_type = "HFSS" @property def odesktop(self): return self._desktop @property def oproject(self): return self._oproject @property def odesign(self): return self._odesign @property def odefinition_manager(self): if self._oproject is None: return None return self._oproject.GetDefinitionManager() def _resolve_material(materials: Any, material_name: str): candidate = None if hasattr(materials, "checkifmaterialexists"): try: candidate = materials.checkifmaterialexists(material_name) except Exception: candidate = None if hasattr(candidate, "permittivity") and hasattr(candidate, "dielectric_loss_tangent"): return candidate if hasattr(materials, "exists_material"): try: candidate = materials.exists_material(material_name) except Exception: candidate = None if hasattr(candidate, "permittivity") and hasattr(candidate, "dielectric_loss_tangent"): return candidate return None def _apply_live_material_properties( renderer: Any, *, permittivity: float, loss_tangent: float, materials_factory: Any | None = None, ) -> bool: live_app = _LiveMaterialApp(renderer) definition_manager = live_app.odefinition_manager if definition_manager is not None and hasattr(definition_manager, "EditMaterial"): definition_manager.EditMaterial("silicon", _cryo_silicon_args(permittivity, loss_tangent)) return True if materials_factory is None: try: from ansys.aedt.core.modules.material_lib import Materials except Exception: Materials = None materials_factory = Materials if materials_factory is None or (live_app.oproject is None and live_app.odesign is None): return False try: live_materials = materials_factory(live_app) silicon = _resolve_material(live_materials, "silicon") if not silicon: return False silicon.permittivity = permittivity silicon.dielectric_loss_tangent = loss_tangent return True except Exception: return False
[docs] def setMaterialProperties( projectname=None, designname=None, solutiontype="Eigenmode", *, renderer: Any | None = None, permittivity: float = 11.45, loss_tangent: float = 1e-7, hfss_factory: Any | None = None, materials_factory: Any | None = None, ): if renderer is not None: pinfo = getattr(renderer, "pinfo", None) if projectname is None: projectname = getattr(pinfo, "project_name", None) if designname is None: designname = getattr(pinfo, "design_name", None) if _apply_live_material_properties( renderer, permittivity=permittivity, loss_tangent=loss_tangent, materials_factory=materials_factory, ): return if projectname is None or designname is None: raise ValueError("Project and design names are required when no live renderer session is available.") if hfss_factory is None: hfss_factory = Hfss aedt = hfss_factory( projectname=projectname, designname=designname, solution_type=solutiontype, new_desktop_session=False, close_on_exit=False, ) try: ultra_cold_silicon(aedt, permittivity=permittivity, loss_tangent=loss_tangent) delete_old_setups(aedt) finally: if hasattr(aedt, "release_desktop"): aedt.release_desktop(close_projects=False, close_desktop=False)
[docs] def ultra_cold_silicon(aedt, *, permittivity: float = 11.45, loss_tangent: float = 1e-7): materials = aedt.materials silicon = _resolve_material(materials, "silicon") if not silicon: raise AttributeError("Could not resolve the silicon material on the active AEDT session.") silicon.permittivity = permittivity silicon.dielectric_loss_tangent = loss_tangent
[docs] def delete_old_setups(aedt): setups = getattr(aedt, "setups", []) if setups: setups[0].delete()
[docs] def get_freq(epra, test_hfss, generate_plots=False): project_name = test_hfss.pinfo.project_name design_name = test_hfss.pinfo.design_name setMaterialProperties(project_name, design_name, solutiontype="Eigenmode", renderer=test_hfss) epra.sim._analyze() if generate_plots: try: epra.sim.plot_convergences() epra.sim.save_screenshot() epra.sim.plot_fields("main") epra.sim.save_screenshot() except Exception as exc: print(f"couldn't generate plots. Error: {exc}") f = epra.get_frequencies() freq = f.values[0][0] * 1e9 print(f"freq = {round(freq / 1e9, 3)} GHz") return freq
[docs] def get_freq_Q_kappa(epra, test_hfss, generate_plots=False): project_name = test_hfss.pinfo.project_name design_name = test_hfss.pinfo.design_name setMaterialProperties(project_name, design_name, solutiontype="Eigenmode", renderer=test_hfss) epra.sim._analyze() if generate_plots: try: epra.sim.plot_convergences() epra.sim.save_screenshot() epra.sim.plot_fields("main") epra.sim.save_screenshot() except Exception: print("couldn't generate plots.") f = epra.get_frequencies() freq = f.values[0][0] * 1e9 Q = f.values[0][1] kappa = freq / Q print(f"freq = {round(freq / 1e9, 3)} GHz") print(f"Q = {round(Q, 1)}") print(f"kappa = {round(kappa / 1e6, 3)} MHz") return freq, Q, kappa
[docs] def mesh_objects(modeler, mesh_lengths): for mesh_name, mesh_info in mesh_lengths.items(): modeler.mesh_length(mesh_name, mesh_info["objects"], MaxLength=mesh_info["MaxLength"])
[docs] def add_ground_strip_and_mesh(modeler, coupler, mesh_lengths): bounds = coupler.qgeometry_bounds() bbox = {"min_x": bounds[0], "max_x": bounds[2], "min_y": bounds[1], "max_y": bounds[3]} center, dimensions = calculate_center_and_dimensions(bbox) modeler.draw_rect_center( [coord * 1e-3 for coord in center], x_size=dimensions[0] * 1e-3, y_size=dimensions[1] * 1e-3, name="ground_strip", ) modeler.intersect(["ground_strip", "ground_main_plane"], True) modeler.subtract("ground_main_plane", ["ground_strip"], True) modeler.assign_perfect_E(["ground_strip"]) mesh_lengths.update({"mesh_ground_strip": {"objects": ["ground_strip"], "MaxLength": "4um"}}) for mesh_name, mesh_info in mesh_lengths.items(): modeler.mesh_length(mesh_name, mesh_info["objects"], MaxLength=mesh_info["MaxLength"])