From c37831e9c1d7746652db487cd721c4a329363b84 Mon Sep 17 00:00:00 2001 From: Sebastien Morais Date: Mon, 19 Feb 2024 13:18:10 +0100 Subject: [PATCH] WIP: temporary removal of some examples --- example/00-EDB/01_edb_example.py | 207 ---------- example/00-EDB/02_edb_to_ipc2581.py | 73 ---- .../03_5G_antenna_example_parametrics.py | 384 ------------------ example/00-EDB/04_edb_parametrized_design.py | 363 ----------------- example/00-EDB/05_Plot_nets.py | 65 --- example/00-EDB/06_Advanced_EDB.py | 175 -------- example/00-EDB/08_CPWG.py | 192 --------- example/00-EDB/09_Configuration.py | 226 ----------- example/00-EDB/10_GDS_workflow.py | 121 ------ .../00-EDB/11_post_layout_parameterization.py | 93 ----- .../00-EDB/12_edb_sma_connector_on_board.py | 220 ---------- example/00-EDB/13_edb_create_component.py | 253 ------------ .../14_edb_create_parametrized_design.py | 113 ------ example/00-EDB/15_ac_analysis.py | 179 -------- 14 files changed, 2664 deletions(-) delete mode 100644 example/00-EDB/01_edb_example.py delete mode 100644 example/00-EDB/02_edb_to_ipc2581.py delete mode 100644 example/00-EDB/03_5G_antenna_example_parametrics.py delete mode 100644 example/00-EDB/04_edb_parametrized_design.py delete mode 100644 example/00-EDB/05_Plot_nets.py delete mode 100644 example/00-EDB/06_Advanced_EDB.py delete mode 100644 example/00-EDB/08_CPWG.py delete mode 100644 example/00-EDB/09_Configuration.py delete mode 100644 example/00-EDB/10_GDS_workflow.py delete mode 100644 example/00-EDB/11_post_layout_parameterization.py delete mode 100644 example/00-EDB/12_edb_sma_connector_on_board.py delete mode 100644 example/00-EDB/13_edb_create_component.py delete mode 100644 example/00-EDB/14_edb_create_parametrized_design.py delete mode 100644 example/00-EDB/15_ac_analysis.py diff --git a/example/00-EDB/01_edb_example.py b/example/00-EDB/01_edb_example.py deleted file mode 100644 index fdf99ab9..00000000 --- a/example/00-EDB/01_edb_example.py +++ /dev/null @@ -1,207 +0,0 @@ -# # EDB: SIwave DC-IR Analysis -# -# This example demonstrates the use of EDB to interact with a PCB -# layout and run DC-IR analysis in SIwave. -# Perform required imports - -# + -import os -import tempfile -import time - -from example.constants import EDB_VERSION -import pyaedt - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -targetfile = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) - -siwave_file = os.path.join(os.path.dirname(targetfile), "ANSYS-HSD_V1.siw") -print(targetfile) -aedt_file = targetfile[:-4] + "aedt" -# - - -# ## Launch Ansys Electronics Database (EDB) -# -# Instantiate an instance of the `pyaedt.Edb` class using SI units. - -# + -if os.path.exists(aedt_file): - os.remove(aedt_file) - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=targetfile, edbversion=edb_version) -# - - -# ## Identify nets and components -# -# The ``Edb.nets.netlist`` and ``Edb.components.components`` properties contain information -# about all of the nets and components. The following cell uses this information to print the -# number of nets and components. - -print("Nets {}".format(len(edb.nets.netlist))) -start = time.time() -print("Components {}".format(len(edb.components.components.keys()))) -print("elapsed time = ", time.time() - start) - -# ## Identify pin positions -# -# This code shows how to obtain all pins for a specific component and -# print the ``[x, y]`` position of each pin. - -pins = edb.components["U2"].pins -count = 0 -for pin in edb.components["U2"].pins.values(): - if count < 10: # Only print the first 10 pin coordinates. - print(pin.position) - elif count == 10: - print("...and many more.") - else: - pass - count += 1 - -# Get all nets connected to a specific component. Print -# the pin and the name of the net that it is connected to. - -connections = edb.components.get_component_net_connection_info("U2") -n_print = 0 # Counter to limit the number of printed lines. -print_max = 15 -for m in range(len(connections["pin_name"])): - ref_des = connections["refdes"][m] - pin_name = connections["pin_name"][m] - net_name = connections["net_name"][m] - if net_name != "" and (n_print < print_max): - print('{}, pin {} -> net "{}"'.format(ref_des, pin_name, net_name)) - n_print += 1 - elif n_print == print_max: - print("...and many more.") - n_print += 1 - -# Compute rats. - -rats = edb.components.get_rats() - -# ## Identify connected nets -# -# The ``get_dcconnected_net_list()`` method retrieves a list of -# all DC-connected power nets. Each group of connected nets is returned -# as a [set](https://docs.python.org/3/tutorial/datastructures.html#sets). -# The first argument to the method is the list of ground nets, which are -# not considered in the search for connected nets. - -GROUND_NETS = ["GND", "GND_DP"] -dc_connected_net_list = edb.nets.get_dcconnected_net_list(GROUND_NETS) -for pnets in dc_connected_net_list: - print(pnets) - -# ## Power Tree -# -# The power tree provides connectivity through all components from the VRM to -# the device. - -VRM = "U1" -OUTPUT_NET = "AVCC_1V3" -powertree_df, component_list_columns, net_group = edb.nets.get_powertree(OUTPUT_NET, GROUND_NETS) - -# Print some information about the power tree. - -print_columns = ["refdes", "pin_name", "component_partname"] -ncol = [component_list_columns.index(c) for c in print_columns] - -# This prints the header. Replace "pin_name" with "pin" to -# make the header align with the values. - -# + -print("\t".join(print_columns).replace("pin_name", "pin")) - -for el in powertree_df: - s = "" - count = 0 - for e in el: - if count in ncol: - s += "{}\t".format(e) - count += 1 - s.rstrip() - print(s) -# - - -# ## Remove unused components -# -# Delete all RLC components that are connected with only one pin. -# The ``Edb.components.delete_single_pin_rlc()`` method -# provides a useful way to -# remove components that are not needed for the simulation. - -edb.components.delete_single_pin_rlc() - -# You can also remove unused components explicitly by name. - -edb.components.delete("C380") - -# Nets can also be removed explicitly. - -edb.nets.delete("PDEN") - -# Print the top and bottom elevation of the stackup obtained using -# the ``Edb.stackup.limits()`` method. - -s = 'Top layer name: "{top}", Elevation: {top_el:.2f} ' -s += 'mm\nBottom layer name: "{bot}", Elevation: {bot_el:2f} mm' -top, top_el, bot, bot_el = edb.stackup.limits() -print(s.format(top=top, top_el=top_el * 1e3, bot=bot, bot_el=bot_el * 1e3)) - -# ## Set up for SIwave DCIR analysis -# -# Create a voltage source and then set up a DCIR analysis. - -edb.siwave.create_voltage_source_on_net("U1", "AVCC_1V3", "U1", "GND", 1.3, 0, "V1") -edb.siwave.create_current_source_on_net("IC2", "NetD3_2", "IC2", "GND", 1.0, 0, "I1") -setup = edb.siwave.add_siwave_dc_analysis("myDCIR_4") -setup.use_dc_custom_settings = True -setup.set_dc_slider = 0 -setup.add_source_terminal_to_ground("V1", 1) - -# ## Solve -# -# Save the modifications and run the analysis in SIwave. - -edb.save_edb() -edb.nets.plot(None, "1_Top", plot_components_on_top=True) - -siw_file = edb.solve_siwave() - -# ## Export results -# -# Export all quantities calculated from the DC-IR analysis. -# The following method runs SIwave in batch mode from the command line. -# Results are written to the edb folder. - -outputs = edb.export_siwave_dc_results( - siw_file, - setup.name, -) - -# Close EDB. After EDB is closed, it can be opened by AEDT. - -edb.close_edb() - -# ## View Layout in SIwave -# -# The SIwave user interface can be visualized and manipulated -# using the SIwave user interface. This command works on Window OS only. - -# + -# siwave = pyaedt.Siwave("2023.2") -# siwave.open_project(siwave_file) -# report_file = os.path.join(temp_folder,'Ansys.htm') - -# siwave.export_siwave_report("myDCIR_4", report_file) -# siwave.close_project() -# siwave.quit_application() -# - - -# Clean up the temporary files and directory. - -temp_dir.cleanup() diff --git a/example/00-EDB/02_edb_to_ipc2581.py b/example/00-EDB/02_edb_to_ipc2581.py deleted file mode 100644 index 11ce55c1..00000000 --- a/example/00-EDB/02_edb_to_ipc2581.py +++ /dev/null @@ -1,73 +0,0 @@ -# # EDB: IPC2581 export -# -# This example shows how you can use PyAEDT to export an IPC2581 file. -# -# Perform required imports, which includes importing a section. - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# - - -# ## Download the AEDB file and copy it in the temporary folder. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -targetfile = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) -ipc2581_file_name = os.path.join(temp_dir.name, "Ansys_Hsd.xml") -print(targetfile) - -# ## Launch EDB -# -# Launch the `pyaedt.Edb` class, using EDB 2023. -# > Note that length dimensions passed to EDB are in SI units. - -# + -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=targetfile, edbversion=edb_version) -# - - -# ## Parametrize the width of a trace. - -edb.modeler.parametrize_trace_width( - "A0_N", parameter_name=pyaedt.generate_unique_name("Par"), variable_value="0.4321mm" -) - -# ## Create a cutout and plot it. - -signal_list = [] -for net in edb.nets.netlist: - if "PCIe" in net: - signal_list.append(net) -power_list = ["GND"] -edb.cutout( - signal_list=signal_list, - reference_list=power_list, - extent_type="ConvexHull", - expansion_size=0.002, - use_round_corner=False, - number_of_threads=4, - remove_single_pin_components=True, - use_pyaedt_extent_computing=True, - extent_defeature=0, -) -edb.nets.plot(None, None, color_by_net=True) - -# ## Export the EDB to an IPC2581 file. - -edb.export_to_ipc2581(ipc2581_file_name, "inch") -print("IPC2581 File has been saved to {}".format(ipc2581_file_name)) - -# ## Close EDB - -edb.close_edb() - -# ## Clean up the temporary directory - -temp_dir.cleanup() diff --git a/example/00-EDB/03_5G_antenna_example_parametrics.py b/example/00-EDB/03_5G_antenna_example_parametrics.py deleted file mode 100644 index 4bfe79b8..00000000 --- a/example/00-EDB/03_5G_antenna_example_parametrics.py +++ /dev/null @@ -1,384 +0,0 @@ -# # EDB: Layout Components -# -# This example shows how you can use EDB to create a parametric component using -# 3D Layout and use it in HFSS 3D. - -# ## Perform required imports -# -# Perform required imports, which includes importing the ``Hfss3dlayout`` object -# and initializing it on version 2023 R2. - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# - - -# ## Set non-graphical mode - -non_graphical = False - -# ## Create data classes -# -# Data classes are useful to do calculations and store variables. -# There are three data classes: ``Patch``, ``Line``, and ``Array``. - -# + -class Patch: - def __init__(self, width=0.0, height=0.0, position=0.0): - self.width = width - self.height = height - self.position = position - - @property - def points(self): - return [ - [self.position, "-{}/2".format(self.height)], - ["{} + {}".format(self.position, self.width), "-{}/2".format(self.height)], - ["{} + {}".format(self.position, self.width), "{}/2".format(self.height)], - [self.position, "{}/2".format(self.height)], - ] - - -class Line: - def __init__(self, length=0.0, width=0.0, position=0.0): - self.length = length - self.width = width - self.position = position - - @property - def points(self): - return [ - [self.position, "-{}/2".format(self.width)], - ["{} + {}".format(self.position, self.length), "-{}/2".format(self.width)], - ["{} + {}".format(self.position, self.length), "{}/2".format(self.width)], - [self.position, "{}/2".format(self.width)], - ] - - -class LinearArray: - def __init__(self, nb_patch=1, array_length=10e-3, array_width=5e-3): - self.nbpatch = nb_patch - self.length = array_length - self.width = array_width - - @property - def points(self): - return [ - [-1e-3, "-{}/2-1e-3".format(self.width)], - ["{}+1e-3".format(self.length), "-{}/2-1e-3".format(self.width)], - ["{}+1e-3".format(self.length), "{}/2+1e-3".format(self.width)], - [-1e-3, "{}/2+1e-3".format(self.width)], - ] - - -# - - -# ## Launch EDB -# -# PyAEDT.Edb allows to open existing Edb project or create a new empty project. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -aedb_path = os.path.join(temp_dir.name, "linear_array.aedb") - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -# Create an instance of the Edb class. -edb = pyaedt.Edb(edbpath=aedb_path, edbversion=edb_version) -# - - -# Add stackup layers - -edb.stackup.add_layer("Virt_GND") -edb.stackup.add_layer( - "Gap", "Virt_GND", layer_type="dielectric", thickness="0.05mm", material="Air" -) -edb.stackup.add_layer("GND", "Gap") -edb.stackup.add_layer( - "Substrat", "GND", layer_type="dielectric", thickness="0.5mm", material="Duroid (tm)" -) -edb.stackup.add_layer("TOP", "Substrat") - -# Create the the first patch and feed line using the ``Patch``, ``Line``classes defined above. -# -# Define parameters: - -# + -edb["w1"] = 1.4e-3 -edb["h1"] = 1.2e-3 -edb["initial_position"] = 0.0 -edb["l1"] = 2.4e-3 -edb["trace_w"] = 0.3e-3 - -first_patch = Patch(width="w1", height="h1", position="initial_position") -edb.modeler.create_polygon(first_patch.points, "TOP", net_name="Array_antenna") -# - - -# First line - -first_line = Line(length="l1", width="trace_w", position=first_patch.width) -edb.modeler.create_polygon(first_line.points, "TOP", net_name="Array_antenna") - -# Now use the ``LinearArray`` class to create the array. - -# + -edb["w2"] = 2.29e-3 -edb["h2"] = 3.3e-3 -edb["l2"] = 1.9e-3 -edb["trace_w2"] = 0.2e-3 - -patch = Patch(width="w2", height="h2") -line = Line(length="l2", width="trace_w2") -linear_array = LinearArray(nb_patch=8, array_width=patch.height) - -current_patch = 1 -current_position = "{} + {}".format(first_line.position, first_line.length) - -while current_patch <= linear_array.nbpatch: - patch.position = current_position - edb.modeler.create_polygon(patch.points, "TOP", net_name="Array_antenna") - current_position = "{} + {}".format(current_position, patch.width) - if current_patch < linear_array.nbpatch: - line.position = current_position - edb.modeler.create_polygon(line.points, "TOP", net_name="Array_antenna") - current_position = "{} + {}".format(current_position, line.length) - current_patch += 1 - -linear_array.length = current_position -# - - -# Add the ground conductor. - -edb.modeler.create_polygon(linear_array.points, "GND", net_name="GND") - -# Add the connector pin to use to assign the port. - -edb.padstacks.create( - padstackname="Connector_pin", holediam="100um", paddiam="0", antipaddiam="200um" -) -con_pin = edb.padstacks.place( - ["{}/4.0".format(first_patch.width), 0], - "Connector_pin", - net_name="Array_antenna", - fromlayer="TOP", - tolayer="GND", - via_name="coax", -) - -# Add a connector ground. - -edb.modeler.create_polygon(first_patch.points, "Virt_GND", net_name="GND") -edb.padstacks.create("gnd_via", "100um", "0", "0") -edb["via_spacing"] = 0.2e-3 -con_ref1 = edb.padstacks.place( - [ - "{} + {}".format(first_patch.points[0][0], "via_spacing"), - "{} + {}".format(first_patch.points[0][1], "via_spacing"), - ], - "gnd_via", - fromlayer="GND", - tolayer="Virt_GND", - net_name="GND", -) -con_ref2 = edb.padstacks.place( - [ - "{} + {}".format(first_patch.points[1][0], "-via_spacing"), - "{} + {}".format(first_patch.points[1][1], "via_spacing"), - ], - "gnd_via", - fromlayer="GND", - tolayer="Virt_GND", - net_name="GND", -) -con_ref3 = edb.padstacks.place( - [ - "{} + {}".format(first_patch.points[2][0], "-via_spacing"), - "{} + {}".format(first_patch.points[2][1], "-via_spacing"), - ], - "gnd_via", - fromlayer="GND", - tolayer="Virt_GND", - net_name="GND", -) -con_ref4 = edb.padstacks.place( - [ - "{} + {}".format(first_patch.points[3][0], "via_spacing"), - "{} + {}".format(first_patch.points[3][1], "-via_spacing"), - ], - "gnd_via", - fromlayer="GND", - tolayer="Virt_GND", - net_name="GND", -) - -# Define the port. - -edb.padstacks.set_solderball(con_pin, "Virt_GND", isTopPlaced=False, ballDiam=0.1e-3) -port_name = edb.padstacks.create_coax_port(con_pin) - -# Display the model using the ``Edb.nets.plot()`` method. - -edb.nets.plot() - -# The EDB is complete. Now close the EDB and import it into HFSS as a "Layout Component". - -edb.save_edb() -edb.close_edb() -print("EDB saved correctly to {}. You can import in AEDT.".format(aedb_path)) - -# ## 3D component in HFSS -# -# First create an instance of the ``pyaedt.Hfss`` class. If you set -# > ``non_graphical = False -# -# then AEDT user interface will be visible after the following cell is executed. -# It is now possible to monitor the progress in the UI as each of the following cells is executed. -# All commands can be run without the UI by changing the value of ``non_graphical``. - -h3d = pyaedt.Hfss( - projectname="Demo_3DComp", - designname="Linear_Array", - specified_version="2023.2", - new_desktop_session=True, - non_graphical=non_graphical, - close_on_exit=True, - solution_type="Terminal", -) - -# Set units to ``mm``. - -h3d.modeler.model_units = "mm" - -# ## Import the EDB as a 3D component -# -# One or more layout components can be imported into HFSS. -# The combination of layout data and 3D CAD data helps streamline model creation and setup. - -component = h3d.modeler.insert_layout_component(aedb_path, parameter_mapping=True) - -# ## Expose the component parameters -# -# If a layout component is parametric, you can expose and change parameters in HFSS - -# + -component.parameters - -w1_name = "{}_{}".format("w1", h3d.modeler.user_defined_component_names[0]) -h3d[w1_name] = 0.0015 -# - - -# ### Radiation Boundary Assignment -# -# The 3D domain includes the air volume surrounding the antenna. -# This antenna will be simulted from 20 GHz - 50 GHz. -# -# A "radiation boundary" will be assigned to the outer boundaries of the domain. -# This boundary should be roughly one quarter wavelength away from the radiating structure: -# -# $$ \lambda/4 = \frac{c_0}{4 f} \approx 2.8mm $$ - -# + -h3d.modeler.fit_all() - -h3d.modeler.create_air_region(2.8, 2.8, 2.8, 2.8, 2.8, 2.8, is_percentage=False) -h3d.assign_radiation_boundary_to_objects("Region") -# - - -# ### Set up analysis -# -# The finite element mesh is adapted iteratively. -# The maximum number of adaptive passes is set using the ``MaximumPasses`` property. -# This model converges such that the $S_{11}$ is independent of the mesh. -# The default accuracy setting is: -# $$ \max(|\Delta S|) < 0.02 $$ - -setup = h3d.create_setup() -setup.props["Frequency"] = "20GHz" -setup.props["MaximumPasses"] = 10 - -# Specify properties of the frequency sweep: - -sweep1 = setup.add_sweep(sweepname="20GHz_to_50GHz") -sweep1.props["RangeStart"] = "20GHz" -sweep1.props["RangeEnd"] = "50GHz" -sweep1.update() - -# Solve the project - -h3d.analyze() - -# ## Plot results outside AEDT -# -# Plot results using Matplotlib. - -trace = h3d.get_traces_for_plot() -solution = h3d.post.get_solution_data(trace[0]) -solution.plot() - -# ## Plot far fields in AEDT -# -# Plot radiation patterns in AEDT. - -# + -variations = {} -variations["Freq"] = ["20GHz"] -variations["Theta"] = ["All"] -variations["Phi"] = ["All"] -h3d.insert_infinite_sphere(name="3D") - -new_report = h3d.post.reports_by_category.far_field( - "db(RealizedGainTotal)", h3d.nominal_adaptive, "3D" -) -new_report.variations = variations -new_report.primary_sweep = "Theta" -new_report.create("Realized2D") -# - - -# ## Plot far fields in AEDT -# -# Plot radiation patterns in AEDT - -new_report.report_type = "3D Polar Plot" -new_report.secondary_sweep = "Phi" -new_report.create("Realized3D") - -# ## Plot far fields outside AEDT -# -# Plot radiation patterns outside AEDT - -solutions_custom = new_report.get_solution_data() -solutions_custom.plot_3d() - -# ## Plot E Field on nets and layers -# -# Plot E Field on nets and layers in AEDT - -h3d.post.create_fieldplot_layers_nets( - [["TOP", "Array_antenna"]], - "Mag_E", - intrinsics={"Freq": "20GHz", "Phase": "0deg"}, - plot_name="E_Layers", -) - -# ## Close AEDT -# -# After the simulation completes, the application can be released from the -# :func:`pyaedt.Desktop.release_desktop` method. -# All methods provide for saving the project before closing AEDT. - -h3d.save_project(os.path.join(temp_dir, "test_layout.aedt")) -h3d.release_desktop() - -# ### Clean up the temporary directory -# -# The following command removes the project and the temporary directory. -# If you'd like to save this project, save it to a folder of your choice prior -# to running the following cell. - -temp_dir.cleanup() diff --git a/example/00-EDB/04_edb_parametrized_design.py b/example/00-EDB/04_edb_parametrized_design.py deleted file mode 100644 index f3e804eb..00000000 --- a/example/00-EDB/04_edb_parametrized_design.py +++ /dev/null @@ -1,363 +0,0 @@ -# # EDB: fully parametrized design -# -# This example shows how to use the EDB interface along with HFSS 3D Layout to create and solve a -# parameterized layout. The layout shows a differential via transition on a printed circuit board -# with back-to-back microstrip to stripline transitions. -# The model is fully parameterized to enable investigation of the transition performance on the -# many degrees of freedom. -# -# The resulting model is shown below -# -# - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# - - -# ## Set non-graphical mode -# -# Set non-graphical mode. The default is ``False``, which opens -# the AEDT UI. - -non_graphical = False - -# ## Launch EDB. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -aedb_path = os.path.join(temp_dir.name, "pcb.aedb") - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=aedb_path, edbversion=edb_version) -# - - -# Define the parameters. - -# + -params = { - "$ms_width": "0.4mm", - "$sl_width": "0.2mm", - "$ms_spacing": "0.2mm", - "$sl_spacing": "0.1mm", - "$via_spacing": "0.5mm", - "$via_diam": "0.3mm", - "$pad_diam": "0.6mm", - "$anti_pad_diam": "0.7mm", - "$pcb_len": "15mm", - "$pcb_w": "5mm", - "$x_size": "1.2mm", - "$y_size": "1mm", - "$corner_rad": "0.5mm", -} - -for par_name in params: - edb.add_project_variable(par_name, params[par_name]) -# - - -# Define the stackup layers from bottom to top. - -layers = [ - {"name": "bottom", "layer_type": "signal", "thickness": "35um", "material": "copper"}, - {"name": "diel_3", "layer_type": "dielectric", "thickness": "275um", "material": "FR4_epoxy"}, - {"name": "sig_2", "layer_type": "signal", "thickness": "35um", "material": "copper"}, - {"name": "diel_2", "layer_type": "dielectric", "thickness": "275um", "material": "FR4_epoxy"}, - {"name": "sig_1", "layer_type": "signal", "thickness": "35um", "material": "copper"}, - {"name": "diel_1", "layer_type": "dielectric", "thickness": "275um", "material": "FR4_epoxy"}, - {"name": "top", "layer_type": "signal", "thickness": "35um", "material": "copper"}, -] - -# Create the EDB stackup. -# Define the bottom layer - -prev = None -for layer in layers: - edb.stackup.add_layer( - layer["name"], - base_layer=prev, - layer_type=layer["layer_type"], - thickness=layer["thickness"], - material=layer["material"], - ) - prev = layer["name"] - -# Create a parametrized padstack for the signal via. - -signal_via_padstack = "automated_via" -edb.padstacks.create( - padstackname=signal_via_padstack, - holediam="$via_diam", - paddiam="$pad_diam", - antipaddiam="", - antipad_shape="Bullet", - x_size="$x_size", - y_size="$y_size", - corner_radius="$corner_rad", - start_layer=layers[-1]["name"], - stop_layer=layers[-3]["name"], -) - -# Assign net names. There are only two signal nets. - -net_p = "p" -net_n = "n" - -# Place the signal vias. - -edb.padstacks.place( - position=["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing)/2"], - definition_name=signal_via_padstack, - net_name=net_p, - via_name="", - rotation=90.0, -) - -edb.padstacks.place( - position=["2*$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing)/2"], - definition_name=signal_via_padstack, - net_name=net_p, - via_name="", - rotation=90.0, -) - -edb.padstacks.place( - position=["$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing)/2"], - definition_name=signal_via_padstack, - net_name=net_n, - via_name="", - rotation=-90.0, -) - -edb.padstacks.place( - position=["2*$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing)/2"], - definition_name=signal_via_padstack, - net_name=net_n, - via_name="", - rotation=-90.0, -) - - -# ## Draw parametrized traces -# -# Trace width and the routing (Microstrip-Stripline-Microstrip). -# Applies to both p and n nets. - -# Trace width, n and p -width = ["$ms_width", "$sl_width", "$ms_width"] -# Routing layer, n and p -route_layer = [layers[-1]["name"], layers[4]["name"], layers[-1]["name"]] - -# Define points for three traces in the "p" net - -points_p = [ - [ - ["0.0", "($ms_width+$ms_spacing)/2"], - ["$pcb_len/3-2*$via_spacing", "($ms_width+$ms_spacing)/2"], - ["$pcb_len/3-$via_spacing", "($ms_width+$ms_spacing+$via_spacing)/2"], - ["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing)/2"], - ], - [ - ["$pcb_len/3", "($ms_width+$sl_spacing+$via_spacing)/2"], - ["$pcb_len/3+$via_spacing", "($ms_width+$sl_spacing+$via_spacing)/2"], - ["$pcb_len/3+2*$via_spacing", "($sl_width+$sl_spacing)/2"], - ["2*$pcb_len/3-2*$via_spacing", "($sl_width+$sl_spacing)/2"], - ["2*$pcb_len/3-$via_spacing", "($ms_width+$sl_spacing+$via_spacing)/2"], - ["2*$pcb_len/3", "($ms_width+$sl_spacing+$via_spacing)/2"], - ], - [ - ["2*$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing)/2"], - ["2*$pcb_len/3+$via_spacing", "($ms_width+$ms_spacing+$via_spacing)/2"], - ["2*$pcb_len/3+2*$via_spacing", "($ms_width+$ms_spacing)/2"], - ["$pcb_len", "($ms_width+$ms_spacing)/2"], - ], -] - -# Define points for three traces in the "n" net - -points_n = [ - [ - ["0.0", "-($ms_width+$ms_spacing)/2"], - ["$pcb_len/3-2*$via_spacing", "-($ms_width+$ms_spacing)/2"], - ["$pcb_len/3-$via_spacing", "-($ms_width+$ms_spacing+$via_spacing)/2"], - ["$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing)/2"], - ], - [ - ["$pcb_len/3", "-($ms_width+$sl_spacing+$via_spacing)/2"], - ["$pcb_len/3+$via_spacing", "-($ms_width+$sl_spacing+$via_spacing)/2"], - ["$pcb_len/3+2*$via_spacing", "-($ms_width+$sl_spacing)/2"], - ["2*$pcb_len/3-2*$via_spacing", "-($ms_width+$sl_spacing)/2"], - ["2*$pcb_len/3-$via_spacing", "-($ms_width+$sl_spacing+$via_spacing)/2"], - ["2*$pcb_len/3", "-($ms_width+$sl_spacing+$via_spacing)/2"], - ], - [ - ["2*$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing)/2"], - ["2*$pcb_len/3 + $via_spacing", "-($ms_width+$ms_spacing+$via_spacing)/2"], - ["2*$pcb_len/3 + 2*$via_spacing", "-($ms_width+$ms_spacing)/2"], - ["$pcb_len", "-($ms_width + $ms_spacing)/2"], - ], -] - -# Add traces to the EDB. - -trace_p = [] -trace_n = [] -for n in range(len(points_p)): - trace_p.append( - edb.modeler.create_trace(points_p[n], route_layer[n], width[n], net_p, "Flat", "Flat") - ) - trace_n.append( - edb.modeler.create_trace(points_n[n], route_layer[n], width[n], net_n, "Flat", "Flat") - ) - -# Create the wave ports - -edb.hfss.create_differential_wave_port( - trace_p[0].id, - ["0.0", "($ms_width+$ms_spacing)/2"], - trace_n[0].id, - ["0.0", "-($ms_width+$ms_spacing)/2"], - "wave_port_1", -) -edb.hfss.create_differential_wave_port( - trace_p[2].id, - ["$pcb_len", "($ms_width+$ms_spacing)/2"], - trace_n[2].id, - ["$pcb_len", "-($ms_width + $ms_spacing)/2"], - "wave_port_2", -) - -# Draw a conducting rectangle on the the ground layers. - -gnd_poly = [ - [0.0, "-$pcb_w/2"], - ["$pcb_len", "-$pcb_w/2"], - ["$pcb_len", "$pcb_w/2"], - [0.0, "$pcb_w/2"], -] -gnd_shape = edb.modeler.Shape("polygon", points=gnd_poly) - -# Void in ground for traces on the signal routing layer - -# + -void_poly = [ - ["$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2"], - [ - "$pcb_len/3 + $via_spacing", - "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2", - ], - ["$pcb_len/3 + 2*$via_spacing", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"], - ["2*$pcb_len/3 - 2*$via_spacing", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"], - [ - "2*$pcb_len/3 - $via_spacing", - "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2", - ], - ["2*$pcb_len/3", "-($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2-$via_spacing/2"], - ["2*$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2+$via_spacing/2"], - [ - "2*$pcb_len/3 - $via_spacing", - "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2+$via_spacing/2", - ], - ["2*$pcb_len/3 - 2*$via_spacing", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"], - ["$pcb_len/3 + 2*$via_spacing", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"], - [ - "$pcb_len/3 + $via_spacing", - "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2+$via_spacing/2", - ], - ["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2+$via_spacing/2"], - ["$pcb_len/3", "($ms_width+$ms_spacing+$via_spacing+$anti_pad_diam)/2"], -] - -void_shape = edb.modeler.Shape("polygon", points=void_poly) -# - - -# Add ground conductors. - -# + -for layer in layers[:-1:2]: - - # add void if the layer is the signal routing layer. - void = [void_shape] if layer["name"] == route_layer[1] else [] - - edb.modeler.create_polygon( - main_shape=gnd_shape, layer_name=layer["name"], voids=void, net_name="gnd" - ) -# - - -# Plot the layout. - -edb.nets.plot(None) - -# Save the EDB. - -edb.save_edb() -edb.close_edb() - -# Open the project in HFSS 3D Layout. - -h3d = pyaedt.Hfss3dLayout( - projectname=aedb_path, - specified_version="2023.2", - non_graphical=non_graphical, - new_desktop_session=True, -) - -# # Add HFSS simulation setup -# -# Add HFSS simulation setup. - -# + -setup = h3d.create_setup() -setup.props["AdaptiveSettings"]["SingleFrequencyDataList"]["AdaptiveFrequencyData"]["MaxPasses"] = 3 - -h3d.create_linear_count_sweep( - setupname=setup.name, - unit="GHz", - freqstart=0, - freqstop=10, - num_of_freq_points=1001, - sweepname="sweep1", - sweep_type="Interpolating", - interpolation_tol_percent=1, - interpolation_max_solutions=255, - save_fields=False, - use_q3d_for_dc=False, -) -# - - -# Define the differential pairs to used to calculate differential and common mode -# s-parameters. - -h3d.set_differential_pair( - diff_name="In", positive_terminal="wave_port_1:T1", negative_terminal="wave_port_1:T2" -) -h3d.set_differential_pair( - diff_name="Out", positive_terminal="wave_port_2:T1", negative_terminal="wave_port_2:T2" -) - -# Solve the project. - -h3d.analyze() - -# Plot the results and shut down AEDT. - -solutions = h3d.post.get_solution_data( - ["dB(S(In,In))", "dB(S(In,Out))"], context="Differential Pairs" -) -solutions.plot() -h3d.release_desktop() - -# Note that the ground nets are only connected to each other due -# to the wave ports. The problem with poor grounding can be seen in the -# S-parameters. This example can be downloaded as a Jupyter Notebook, so -# you can modify it. Try changing parameters or adding ground vias to improve performance. -# -# The final cell cleans up the temporary directory, removing all files. - -temp_dir.cleanup() diff --git a/example/00-EDB/05_Plot_nets.py b/example/00-EDB/05_Plot_nets.py deleted file mode 100644 index fbd11ab8..00000000 --- a/example/00-EDB/05_Plot_nets.py +++ /dev/null @@ -1,65 +0,0 @@ -# # EDB: plot nets with Matplotlib -# -# This example shows how to use the ``Edb`` class to view nets, layers and -# via geometry directly in Python. The methods demonstrated in this example -# rely on -# [matplotlib](https://matplotlib.org/cheatsheets/_images/cheatsheets-1.png). - -# ## Perform required imports -# -# Perform required imports, which includes importing a section. - -# + -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# - - -# ## Download the EDB and copy it into the temporary folder. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -targetfolder = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) - -# ## Create an instance of the Electronics Database using the `pyaedt.Edb` class. -# -# > Note that units are SI. - -# + -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=targetfolder, edbversion=edb_version) -# - - -# Display the nets on a layer. You can display the net geometry directly in Python using -# ``matplotlib`` from the ``pyaedt.Edb`` class. - -edb.nets.plot("AVCC_1V3") - -# You can view multiple nets by passing a list containing the net -# names to the ``plot()`` method. - -edb.nets.plot(["GND", "GND_DP", "AVCC_1V3"], color_by_net=True) - -# You can display all copper on a single layer by passing ``None`` -# as the first argument. The second argument is a list -# of layers to plot. In this case, only one -# layer is to be displayed. - -edb.nets.plot(None, ["1_Top"], color_by_net=True, plot_components_on_top=True) - -# Display a side view of the layers and padstack geometry using the -# ``Edb.stackup.plot()`` method. - -edb.stackup.plot(scale_elevation=False, plot_definitions=["c100hn140", "c35"]) - -# Close the EDB. - -edb.close_edb() - -# Remove all files and the temporary directory. - -temp_dir.cleanup() diff --git a/example/00-EDB/06_Advanced_EDB.py b/example/00-EDB/06_Advanced_EDB.py deleted file mode 100644 index b31e6fe8..00000000 --- a/example/00-EDB/06_Advanced_EDB.py +++ /dev/null @@ -1,175 +0,0 @@ -# # EDB: parametric via creation -# -# This example shows how you can use EDB to create a layout. -# -# First import the required Python packages. - - -import os -import tempfile - -from example.constants import EDB_VERSION -import numpy as np -import pyaedt - -# Create the EDB project. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -aedb_path = os.path.join(temp_dir.name, "parametric_via.aedb") - -# ## Create stackup -# -# The ``StackupSimple`` class creates a stackup based on few inputs. This stackup -# is used later. -# -# Define a function to create the ground conductor. - - -def create_ground_planes(edb, layers): - plane = edb.modeler.Shape("rectangle", pointA=["-3mm", "-3mm"], pointB=["3mm", "3mm"]) - for i in layers: - edb.modeler.create_polygon(plane, i, net_name="GND") - - -# ## Create the EDB -# -# Create the EDB instance. -# If the path doesn't exist, PyAEDT automatically generates a new AEDB folder. - -# + -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=aedb_path, edbversion=edb_version) -# - - -# Insert the stackup layers. - -layout_count = 12 -diel_material_name = "FR4_epoxy" -diel_thickness = "0.15mm" -cond_thickness_outer = "0.05mm" -cond_thickness_inner = "0.017mm" -soldermask_thickness = "0.05mm" -trace_in_layer = "TOP" -trace_out_layer = "L10" -gvia_num = 10 -gvia_angle = 30 -edb.stackup.create_symmetric_stackup( - layer_count=layout_count, - inner_layer_thickness=cond_thickness_inner, - outer_layer_thickness=cond_thickness_outer, - soldermask_thickness=soldermask_thickness, - dielectric_thickness=diel_thickness, - dielectric_material=diel_material_name, -) - -# ## Define parameters -# -# Define parameters to allow changes in the model dimesons. Parameters preceded by -# the ``$`` character have project-wide scope. -# Without the ``$`` prefix, the parameter scope is limited to the design. - -# + -giva_angle_rad = gvia_angle / 180 * np.pi - -edb["$via_hole_size"] = "0.3mm" -edb["$antipaddiam"] = "0.7mm" -edb["$paddiam"] = "0.5mm" -edb.add_design_variable("via_pitch", "1mm", is_parameter=True) -edb.add_design_variable("trace_in_width", "0.2mm", is_parameter=True) -edb.add_design_variable("trace_out_width", "0.1mm", is_parameter=True) -# - - -# ## Define padstacks -# -# Create two padstck definitions, one for the ground via and one for the signal via. - -edb.padstacks.create( - padstackname="SVIA", - holediam="$via_hole_size", - antipaddiam="$antipaddiam", - paddiam="$paddiam", - start_layer=trace_in_layer, - stop_layer=trace_out_layer, -) -edb.padstacks.create(padstackname="GVIA", holediam="0.3mm", antipaddiam="0.7mm", paddiam="0.5mm") - -# Place the signal via. - -edb.padstacks.place([0, 0], "SVIA", net_name="RF") - -# Place the ground vias. - -# + -gvia_num_side = gvia_num / 2 - -if gvia_num_side % 2: - - # Even number of ground vias on each side - edb.padstacks.place(["via_pitch", 0], "GVIA", net_name="GND") - edb.padstacks.place(["via_pitch*-1", 0], "GVIA", net_name="GND") - for i in np.arange(1, gvia_num_side / 2): - xloc = "{}*{}".format(np.cos(giva_angle_rad * i), "via_pitch") - yloc = "{}*{}".format(np.sin(giva_angle_rad * i), "via_pitch") - edb.padstacks.place([xloc, yloc], "GVIA", net_name="GND") - edb.padstacks.place([xloc, yloc + "*-1"], "GVIA", net_name="GND") - - edb.padstacks.place([xloc + "*-1", yloc], "GVIA", net_name="GND") - edb.padstacks.place([xloc + "*-1", yloc + "*-1"], "GVIA", net_name="GND") -else: - - # Odd number of ground vias on each side - for i in np.arange(0, gvia_num_side / 2): - xloc = "{}*{}".format(np.cos(giva_angle_rad * (i + 0.5)), "via_pitch") - yloc = "{}*{}".format(np.sin(giva_angle_rad * (i + 0.5)), "via_pitch") - edb.padstacks.place([xloc, yloc], "GVIA", net_name="GND") - edb.padstacks.place([xloc, yloc + "*-1"], "GVIA", net_name="GND") - - edb.padstacks.place([xloc + "*-1", yloc], "GVIA", net_name="GND") - edb.padstacks.place([xloc + "*-1", yloc + "*-1"], "GVIA", net_name="GND") -# - - -# Draw the traces - -# + -edb.modeler.create_trace( - [[0, 0], [0, "-3mm"]], - layer_name=trace_in_layer, - net_name="RF", - width="trace_in_width", - start_cap_style="Flat", - end_cap_style="Flat", -) - -edb.modeler.create_trace( - [[0, 0], [0, "3mm"]], - layer_name=trace_out_layer, - net_name="RF", - width="trace_out_width", - start_cap_style="Flat", - end_cap_style="Flat", -) -# - - -# Draw ground conductors - -ground_layers = [i for i in edb.stackup.signal_layers.keys()] -ground_layers.remove(trace_in_layer) -ground_layers.remove(trace_out_layer) -create_ground_planes(edb=edb, layers=ground_layers) - -# Display the layout - -edb.stackup.plot(plot_definitions=["GVIA", "SVIA"]) - -# Save EDB and close the EDB. - -edb.save_edb() -edb.close_edb() -print("aedb Saved in {}".format(aedb_path)) - -# Clean up the temporary directory. - -temp_dir.cleanup() diff --git a/example/00-EDB/08_CPWG.py b/example/00-EDB/08_CPWG.py deleted file mode 100644 index 34918df3..00000000 --- a/example/00-EDB/08_CPWG.py +++ /dev/null @@ -1,192 +0,0 @@ -# # EDB: fully parametrized CPWG design - -# This example shows how you can use HFSS 3D Layout to create a parametric design -# for a CPWG (coplanar waveguide with ground). - - -# ## Perform required imports - -# Perform required imports. Importing the ``Hfss3dlayout`` object initializes it -# on version 2023 R2. - -import os - -from example.constants import EDB_VERSION -import numpy as np -import pyaedt - -# ## Set non-graphical mode - -# Set non-graphical mode. The default is ``False``. - -non_graphical = False - -# ## Launch EDB - -# + -aedb_path = os.path.join( - pyaedt.generate_unique_folder_name(), pyaedt.generate_unique_name("pcb") + ".aedb" -) -print(aedb_path) - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edbapp = pyaedt.Edb(edbpath=aedb_path, edbversion=edb_version) -# - - -# ## Define parameters - -params = { - "$ms_width": "0.4mm", - "$ms_clearance": "0.3mm", - "$ms_length": "20mm", -} -for par_name in params: - edbapp.add_project_variable(par_name, params[par_name]) - - -# ## Create s symmetric stackup - -edbapp.stackup.create_symmetric_stackup(2) -edbapp.stackup.plot() - -# ## Draw planes - -# + -plane_lw_pt = ["0mm", "-3mm"] -plane_up_pt = ["$ms_length", "3mm"] - -top_layer_obj = edbapp.modeler.create_rectangle( - "TOP", net_name="gnd", lower_left_point=plane_lw_pt, upper_right_point=plane_up_pt -) -bot_layer_obj = edbapp.modeler.create_rectangle( - "BOTTOM", net_name="gnd", lower_left_point=plane_lw_pt, upper_right_point=plane_up_pt -) -layer_dict = {"TOP": top_layer_obj, "BOTTOM": bot_layer_obj} -# - - -# ## Draw a trace - -trace_path = [["0", "0"], ["$ms_length", "0"]] -edbapp.modeler.create_trace( - trace_path, - layer_name="TOP", - width="$ms_width", - net_name="sig", - start_cap_style="Flat", - end_cap_style="Flat", -) - -# ## Create a trace to plane clearance - -poly_void = edbapp.modeler.create_trace( - trace_path, - layer_name="TOP", - net_name="gnd", - width="{}+2*{}".format("$ms_width", "$ms_clearance"), - start_cap_style="Flat", - end_cap_style="Flat", -) -edbapp.modeler.add_void(layer_dict["TOP"], poly_void) - -# ## Create a ground via padstack and place ground stitching vias - -# + -edbapp.padstacks.create( - padstackname="GVIA", - holediam="0.3mm", - paddiam="0.5mm", -) - -yloc_u = "$ms_width/2+$ms_clearance+0.25mm" -yloc_l = "-$ms_width/2-$ms_clearance-0.25mm" - -for i in np.arange(1, 20): - edbapp.padstacks.place([str(i) + "mm", yloc_u], "GVIA", net_name="GND") - edbapp.padstacks.place([str(i) + "mm", yloc_l], "GVIA", net_name="GND") -# - - -# ## Save and close EDB - -edbapp.save_edb() -edbapp.close_edb() - -# ## Open EDB in AEDT - -h3d = pyaedt.Hfss3dLayout( - projectname=aedb_path, - specified_version="2023.2", - non_graphical=non_graphical, - new_desktop_session=True, -) - -# ## Create wave ports - -h3d.create_edge_port( - "line_3", 0, iswave=True, wave_vertical_extension=10, wave_horizontal_extension=10 -) -h3d.create_edge_port( - "line_3", 2, iswave=True, wave_vertical_extension=10, wave_horizontal_extension=10 -) - -# ## Edit airbox extents - -h3d.edit_hfss_extents(air_vertical_positive_padding="10mm", air_vertical_negative_padding="1mm") - -# ## Create setup - -setup = h3d.create_setup() -setup["MaxPasses"] = 2 -setup["AdaptiveFrequency"] = "3GHz" -setup["SaveAdaptiveCurrents"] = True -h3d.create_linear_count_sweep( - setupname=setup.name, - unit="GHz", - freqstart=0, - freqstop=5, - num_of_freq_points=1001, - sweepname="sweep1", - sweep_type="Interpolating", - interpolation_tol_percent=1, - interpolation_max_solutions=255, - save_fields=False, - use_q3d_for_dc=False, -) - -# ## Plot layout - -# + -h3d.modeler.edb.nets.plot(None, None, color_by_net=True) - -cp_name = h3d.modeler.clip_plane() - -h3d.save_project() -# - - -# ## Start HFSS solver - -# Start the HFSS solver by uncommenting the ``h3d.analyze()`` command. - -# + -# h3d.analyze() -# - - -# ## Save AEDT - -# + -aedt_path = aedb_path.replace(".aedb", ".aedt") -h3d.logger.info("Your AEDT project is saved to {}".format(aedt_path)) -solutions = h3d.get_touchstone_data()[0] -solutions.log_x = False -solutions.plot() - -h3d.post.create_fieldplot_cutplane( - cp_name, "Mag_E", h3d.nominal_adaptive, intrinsincDict={"Freq": "3GHz", "Phase": "0deg"} -) -# - - -# ## Release AEDT - -h3d.release_desktop() diff --git a/example/00-EDB/09_Configuration.py b/example/00-EDB/09_Configuration.py deleted file mode 100644 index cde7f357..00000000 --- a/example/00-EDB/09_Configuration.py +++ /dev/null @@ -1,226 +0,0 @@ -# # EDB: Pin to Pin project -# -# This example demonstrates the use of the Electronics -# Database (EDB) interface to create a layout using the BOM and -# a configuration file. - -# ## Perform required imports -# -# The ``Hfss3dlayout`` class provides an interface to -# the 3D Layout editor in AEDT. -# on version 2023 R2. - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# - - -# Download the AEDB file and copy it to a temporary folder. - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -target_aedb = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) -print("Project folder is", target_aedb) - -# ## Launch EDB -# -# Launch the ``pyaedt.Edb`` class using EDB 2023 R2. Length units are SI. - -# + -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edbapp = pyaedt.Edb(target_aedb, edbversion=edb_version) -# - - -# ## Import definitions -# -# The definition file uses the [json](https://www.json.org/json-en.html) to -# map layout part numbers to their corresponding models. -# -# The model may be an RLC, S-parameter, or -# [SPICE](https://en.wikipedia.org/wiki/SPICE) model definition. -# Once imported, the definition is applied to the components in the layout. -# In this example, the JSON file is in the ``*.aedb`` folder and has the following format: -# ``` json -# { -# "SParameterModel": { -# "GRM32_DC0V_25degC_series": "./GRM32_DC0V_25degC_series.s2p" -# }, -# "SPICEModel": { -# "GRM32_DC0V_25degC": "./GRM32_DC0V_25degC.mod" -# }, -# "Definitions": { -# "CAPC1005X05N": { -# "Component_type": "Capacitor", -# "Model_type": "RLC", -# "Res": 1, -# "Ind": 2, -# "Cap": 3, -# "Is_parallel": false -# }, -# "'CAPC3216X180X55ML20T25": { -# "Component_type": "Capacitor", -# "Model_type": "SParameterModel", -# "Model_name": "GRM32_DC0V_25degC_series" -# }, -# "'CAPC3216X180X20ML20": { -# "Component_type": "Capacitor", -# "Model_type": "SPICEModel", -# "Model_name": "GRM32_DC0V_25degC" -# } -# } -# } -# ``` -# -# The ``Edb.components.import_definitions()`` method imports the component definitions that map -# electrical models to the components in the simulation model. - -edbapp.components.import_definition(os.path.join(target_aedb, "1_comp_definition.json")) - -# ## Import BOM -# -# The bill of materials (BOM) file provides the list of all components -# by reference designator, part name, component type, and nominal value. -# -# Components that are not contained in the BOM are deactivated in the -# simulation model. -# This example saves the CSV file in the ``aedb`` folder. -# -# ``` -# +------------+-----------------------+-----------+------------+ -# | RefDes | Part name | Type | Value | -# +============+=======================+===========+============+ -# | C380 | CAPC1005X55X25LL05T10 | Capacitor | 11nF | -# +------------+-----------------------+-----------+------------+ -# ``` -# -# Having red the information in the BOM and definitions file, electrical models can be -# assigned to all of the components in the simulation model. - -edbapp.components.import_bom( - os.path.join(target_aedb, "0_bom.csv"), - refdes_col=0, - part_name_col=1, - comp_type_col=2, - value_col=3, -) - -# ## Verify a Component -# -# Component property allows to access all components instances and their property with -# getters and setters. - -comp = edbapp.components["C1"] -comp.model_type, comp.value - -# ## Check component definition -# -# When an s-parameter model is associated to a component it will be available in -# nport_comp_definition property. - -edbapp.components.nport_comp_definition -edbapp.save_edb() - -# ## Configure the simulation setup -# -# This step enables the following: - -# - Definition of the nets to include in the cutout region -# - Cutout details -# - Components to create the ports on -# - Simulation settings -# -# The ``Edb.new_simulaton_configuration()`` method returns an instance -# of the ``SimulationConfiguration`` class. - -# + -sim_setup = edbapp.new_simulation_configuration() -sim_setup.solver_type = sim_setup.SOLVER_TYPE.SiwaveSYZ -sim_setup.batch_solve_settings.cutout_subdesign_expansion = 0.003 -sim_setup.batch_solve_settings.do_cutout_subdesign = True -sim_setup.batch_solve_settings.use_pyaedt_cutout = True -sim_setup.ac_settings.max_arc_points = 6 -sim_setup.ac_settings.max_num_passes = 5 - -sim_setup.batch_solve_settings.signal_nets = [ - "PCIe_Gen4_TX2_CAP_P", - "PCIe_Gen4_TX2_CAP_N", - "PCIe_Gen4_TX2_P", - "PCIe_Gen4_TX2_N", -] -sim_setup.batch_solve_settings.components = ["U1", "X1"] -sim_setup.batch_solve_settings.power_nets = ["GND", "GND_DP"] -sim_setup.ac_settings.start_freq = "100Hz" -sim_setup.ac_settings.stop_freq = "6GHz" -sim_setup.ac_settings.step_freq = "10MHz" -# - - -# ## Implement the setup -# -# The cutout and all other simulation settings are applied to the simulation model. - -sim_setup.export_json(os.path.join(temp_dir.name, "configuration.json")) -edbapp.build_simulation_project(sim_setup) - -# ## Display the cutout -# -# Plot cutout once finished. The model is ready to simulate. - -edbapp.nets.plot(None, None) - -# ## Save and close EDB -# -# EDB is saved and re-opened in HFSS -# 3D Layout, where the HFSS simulation can be run. - -edbapp.save_edb() -edbapp.close_edb() - -# ## Open Electronics Desktop -# -# The EDB is opened in AEDT Hfss3DLayout. -# -# Set ``non_graphical=True`` to run the simulation in non-graphical mode. - -h3d = pyaedt.Hfss3dLayout( - specified_version="2023.2", - projectname=target_aedb, - non_graphical=False, - new_desktop_session=False, -) - -# ## Analyze -# -# This project is ready to solve. -# Executing the following cell runs the HFSS simulation on the layout. - -h3d.analyze() - -# ## View results -# -# S-parameter data is loaded at the end of simulation. - -solutions = h3d.post.get_solution_data() - -# ## Plot results -# -# Plot S-Parameter data. - -solutions.plot(solutions.expressions, "db20") - -# ## Save and close AEDT -# -# HFSS 3D Layout is saved and closed. - -h3d.save_project() -h3d.release_desktop() - -# Clean up the temporary directory. All files and the temporary project -# folder will be deleted in the next step. - -temp_dir.cleanup() diff --git a/example/00-EDB/10_GDS_workflow.py b/example/00-EDB/10_GDS_workflow.py deleted file mode 100644 index d71714ac..00000000 --- a/example/00-EDB/10_GDS_workflow.py +++ /dev/null @@ -1,121 +0,0 @@ -# # EDB: Edit Control File and import gds -# -# This example demonstrates how to import a gds layout for subsequent -# simulation with HFSS. - -# Perform imports. - -# + -import os -import shutil -import tempfile - -from example.constants import EDB_VERSION -import pyaedt -from pyaedt.edb_core.edb_data.control_file import ControlFile - -# - - -# ## Fetch Example Data -# -# Download the EDB folder and copy it to a temporary folder. -# The following files are used in this example: -# - _sky130_fictious_dtc_exmple_contol_no_map.xml_ -# defines physical information such -# as material properties, stackup layers, and boundary conditions. -# - _dummy_layermap.map_ -# maps properties to stackup layers. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -control_fn = "sky130_fictitious_dtc_example_control_no_map.xml" -gds_fn = "sky130_fictitious_dtc_example.gds" -layer_map = "dummy_layermap.map" - -local_path = pyaedt.downloads.download_file("gds", destination=temp_dir.name) -c_file_in = os.path.join(local_path, control_fn) -c_map = os.path.join(local_path, layer_map) -gds_in = os.path.join(local_path, gds_fn) -gds_out = os.path.join(temp_dir, "gds_out.gds") -shutil.copy2(gds_in, gds_out) -# - - -# ## Control file -# -# A Control file is an xml file which purpose if to provide additional information during -# import phase. It can include, materials, stackup, setup, boundaries and settings. -# In this example we will import an existing xml, integrate it with a layer mapping file of gds -# and then adding setup and boundaries. - -c = ControlFile(c_file_in, layer_map=c_map) - -# ## Set up simulation -# -# This code sets up a simulation with HFSS and adds a frequency sweep. - -setup = c.setups.add_setup("Setup1", "1GHz") -setup.add_sweep("Sweep1", "0.01GHz", "5GHz", "0.1GHz") - -# ## Provide additional stackup settings -# -# After import, you can change the stackup settings and add or remove layers or materials. - -c.stackup.units = "um" -c.stackup.dielectrics_base_elevation = -100 -c.stackup.metal_layer_snapping_tolerance = "10nm" -for via in c.stackup.vias: - via.create_via_group = True - via.snap_via_group = True - -# ## Define boundary settings -# -# Boundaries can include ports, components and boundary extent. - -c.boundaries.units = "um" -c.boundaries.add_port("P1", x1=223.7, y1=222.6, layer1="Metal6", x2=223.7, y2=100, layer2="Metal6") -c.boundaries.add_extent() -comp = c.components.add_component("B1", "BGA", "IC", "Flip chip", "Cylinder") -comp.solder_diameter = "65um" -comp.add_pin("1", "81.28", "84.6", "met2") -comp.add_pin("2", "211.28", "84.6", "met2") -comp.add_pin("3", "211.28", "214.6", "met2") -comp.add_pin("4", "81.28", "214.6", "met2") -c.import_options.import_dummy_nets = True - -# ## Write XML file -# -# After all settings are ready, you can write an XML file. - -c.write_xml(os.path.join(temp_dir.name, "output.xml")) - -# ## Open EDB -# -# Import the gds and open the edb. - -# + -from pyaedt import Edb - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = Edb( - gds_out, edbversion=edb_version, technology_file=os.path.join(temp_dir.name, "output.xml") -) -# - - -# ## Plot stackup -# -# Plot the stackup. - -edb.stackup.plot(first_layer="met1") - -# ## Close EDB -# -# Close the project. - -edb.close_edb() - -# Clean up the temporary folder. - -temp_dir.cleanup() diff --git a/example/00-EDB/11_post_layout_parameterization.py b/example/00-EDB/11_post_layout_parameterization.py deleted file mode 100644 index 5296f40b..00000000 --- a/example/00-EDB/11_post_layout_parameterization.py +++ /dev/null @@ -1,93 +0,0 @@ -# # EDB: post-layout parameterization -# -# This example shows you how to parameterize the signal net in post-layout. -# -# Define input parameters. - -signal_net_name = "DDR4_ALERT3" -coplanar_plane_net_name = "1V0" # Specify name of coplanar plane net for adding clearance -layers = ["16_Bottom"] # Specify layers to parameterize - -# Perform required imports. - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") - -# Download and open example layout file in edb format. - -edb_path = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edb_path, edbversion=edb_version) -# - - -# ## Create cutout -# -# The ``Edb.cutout()`` method takes a list of -# signal nets as the first argument and a list of -# reference nets as the second argument. - -edb.cutout([signal_net_name], [coplanar_plane_net_name, "GND"], remove_single_pin_components=True) - -# Retrieve the path segments from the signal net. - -net = edb.nets[signal_net_name] -trace_segments = [] -for p in net.primitives: - if p.layer_name not in layers: - continue - if not p.type == "Path": - continue - trace_segments.append(p) - -# Create and assign delta w variable per layer. - -for p in trace_segments: - vname = f"{p.net_name}_{p.layer_name}_dw" - if vname not in edb.variables: - edb[vname] = "0mm" - new_w = f"{p.width}+{vname}" - p.width = new_w - -# Delete existing clearance. - -for p in trace_segments: - for g in edb.modeler.get_polygons_by_layer(p.layer_name, coplanar_plane_net_name): - for v in g.voids: - if p.is_intersecting(v): - v.delete() - -# Create and assign the clearance variable for each layer. - -for p in trace_segments: - clr = f"{p.net_name}_{p.layer_name}_clr" - if clr not in edb.variables: - edb[clr] = "0.5mm" - path = p.get_center_line() - for g in edb.modeler.get_polygons_by_layer(p.layer_name, coplanar_plane_net_name): - void = edb.modeler.create_trace(path, p.layer_name, f"{p.width}+{clr}*2") - g.add_void(void) - -# Visualize the layout. - -edb.nets.plot(layers=layers[0], size=2000) - -# Save the AEDB file and close EDB. - -save_edb_path = os.path.join(temp_dir.name, "post_layout_parameterization.aedb") -edb.save_edb_as(save_edb_path) -print("Edb is saved to ", save_edb_path) -edb.close_edb() - -# Clean up the temporary folder. - -temp_dir.cleanup() diff --git a/example/00-EDB/12_edb_sma_connector_on_board.py b/example/00-EDB/12_edb_sma_connector_on_board.py deleted file mode 100644 index bd559616..00000000 --- a/example/00-EDB/12_edb_sma_connector_on_board.py +++ /dev/null @@ -1,220 +0,0 @@ -# # EDB: geometry creation -# -# This example shows how to -# 1. Create a parameterized PCB with an SMA connector footprint for a single-ended -# SMA connector launch footprint.. -# 2. Place 3D component on PCB. -# 3. Create HFSS setup and frequency sweep with a mesh operation. -# 4. Create return loss plot - -# ## See the finished project -# -# - -# ## Create a parameterized PCB -# -# Import dependencies. - -import os -import tempfile - -from example.constants import EDB_VERSION -import numpy as np -import pyaedt - -# Create the EDB. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -working_folder = temp_dir.name - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -aedb_path = os.path.join(working_folder, "pcb.aedb") -print("AEDB file is located in {}".format(aedb_path)) - -edb = pyaedt.Edb(edbpath=aedb_path, edbversion=edb_version) -# - - -# Add the FR4 dielectric for the PCB. - -edb.materials.add_dielectric_material("ANSYS_FR4", 3.5, 0.005) - -# ## Create Stackup -# -# While this code explicitly defines the stackup, you can import it -# from a from a CSV or XML file using the -# ``Edb.stackup.import_stackup()`` method. - -edb.add_design_variable("$DIEL_T", "0.15mm") -edb.stackup.add_layer("BOT") -edb.stackup.add_layer( - "D5", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4" -) -edb.stackup.add_layer("L5", "Diel", thickness="0.05mm") -edb.stackup.add_layer( - "D4", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4" -) -edb.stackup.add_layer("L4", "Diel", thickness="0.05mm") -edb.stackup.add_layer( - "D3", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4" -) -edb.stackup.add_layer("L3", "Diel", thickness="0.05mm") -edb.stackup.add_layer( - "D2", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4" -) -edb.stackup.add_layer("L2", "Diel", thickness="0.05mm") -edb.stackup.add_layer( - "D1", "GND", layer_type="dielectric", thickness="$DIEL_T", material="ANSYS_FR4" -) -edb.stackup.add_layer("TOP", "Diel", thickness="0.05mm") - -# Create ground conductors. - -# + -edb.add_design_variable("PCB_W", "20mm") -edb.add_design_variable("PCB_L", "20mm") - -gnd_dict = {} -for layer_name in edb.stackup.signal_layers.keys(): - gnd_dict[layer_name] = edb.modeler.create_rectangle( - layer_name, "GND", [0, "PCB_W/-2"], ["PCB_L", "PCB_W/2"] - ) -# - - -# ## Create signal net -# -# Create signal net on layer 3, and add clearance to the ground plane. - -# + -edb.add_design_variable("SIG_L", "10mm") -edb.add_design_variable("SIG_W", "0.1mm") -edb.add_design_variable("SIG_C", "0.3mm") - -signal_path = (["5mm", 0], ["SIG_L+5mm", 0]) -signal_trace = edb.modeler.create_trace(signal_path, "L3", "SIG_W", "SIG", "Flat", "Flat") - -signal_path = (["5mm", 0], ["PCB_L", 0]) -clr = edb.modeler.create_trace(signal_path, "L3", "SIG_C*2+SIG_W", "SIG", "Flat", "Flat") -gnd_dict["L3"].add_void(clr) -# - - -# ## Place signal vias -# -# Create the via padstack definition and place the signal vias. - -edb.add_design_variable("SG_VIA_D", "1mm") -edb.add_design_variable("$VIA_AP_D", "1.2mm") -edb.padstacks.create("ANSYS_VIA", "0.3mm", "0.5mm", "$VIA_AP_D") -edb.padstacks.place(["5mm", 0], "ANSYS_VIA", "SIG") - -# Create ground vias around the SMA -# connector launch footprint. The vias -# are placed around the circumference -# of the launch from 35 degrees to 325 -# degrees. - -for i in np.arange(30, 326, 35): - px = np.cos(i / 180 * np.pi) - py = np.sin(i / 180 * np.pi) - edb.padstacks.place( - ["{}*{}+5mm".format("SG_VIA_D", px), "{}*{}".format("SG_VIA_D", py)], "ANSYS_VIA", "GND" - ) - -# Create ground vias along the signal trace. - -for i in np.arange(2e-3, edb.variables["SIG_L"].value - 2e-3, 2e-3): - edb.padstacks.place(["{}+5mm".format(i), "1mm"], "ANSYS_VIA", "GND") - edb.padstacks.place(["{}+5mm".format(i), "-1mm"], "ANSYS_VIA", "GND") - -# Create a wave port at the end of the signal trace. - -signal_trace.create_edge_port("port_1", "End", "Wave", horizontal_extent_factor=10) - -# ## Set up HFSS simulation -# -# The ``max_num_passes`` argument sets an upper limit on the -# number of adaptive passes for mesh refinement. -# -# For broadband applications when the simulation results may be used -# to generate a SPICE model, the outer domain boundary can be -# located roughly $$ d=\lambda/8 $$ from the internal structures -# in the model. - -# + -extend_domain = 3e11 / 5e9 / 8.0 # Quarter wavelength at 4 GHz. -edb.design_options.antipads_always_on = True -edb.hfss.hfss_extent_info.air_box_horizontal_extent = extend_domain -edb.hfss.hfss_extent_info.air_box_positive_vertical_extent = extend_domain -edb.hfss.hfss_extent_info.air_box_negative_vertical_extent = extend_domain - -setup = edb.create_hfss_setup("Setup1") -setup.set_solution_single_frequency("5GHz", max_num_passes=8, max_delta_s="0.02") -setup.hfss_solver_settings.order_basis = "first" -# - - -# Add a mesh operation to the setup. - -edb.setups["Setup1"].add_length_mesh_operation({"SIG": ["L3"]}, "m1", max_length="0.1mm") - -# Add a frequency sweep to setup. -# -# When the simulation results are to -# be used for transient SPICE analysis, you should -# use the following strategy: -# -# - DC point -# - Logarithmic sweep from 1 kHz to 100 MHz -# - Linear scale for higher frequencies. - -setup.add_frequency_sweep( - "Sweep1", - frequency_sweep=[ - ["linear count", "0", "1KHz", 1], - ["log scale", "1KHz", "100MHz", 10], - ["linear scale", "0.1GHz", "5GHz", "0.1GHz"], - ], -) - -# Save and close EDB. - -edb.save_edb() -edb.close_edb() - -# Launch HFSS 3D Layout. - -h3d = pyaedt.Hfss3dLayout(aedb_path, specified_version=edb_version, new_desktop_session=True) - -# Place a 3D component. - -full_comp_name = pyaedt.downloads.download_file( - "component_3d", filename="SMA_RF_SURFACE_MOUNT.a3dcomp", destination=working_folder -) -comp = h3d.modeler.place_3d_component( - component_path=full_comp_name, - number_of_terminals=1, - placement_layer="TOP", - component_name="my_connector", - pos_x="5mm", - pos_y=0.000, -) - -# ## Run simulation - -h3d.analyze(num_cores=4) - -# ## Visualize the return loss. - -h3d.post.create_report("dB(S(port_1, port_1))") - -# ## Save and close the project. - -h3d.save_project() -print("Project is saved to {}".format(h3d.project_path)) -h3d.release_desktop(True, True) - -# ## Clean up the temporary folder. - -temp_dir.cleanup() diff --git a/example/00-EDB/13_edb_create_component.py b/example/00-EDB/13_edb_create_component.py deleted file mode 100644 index f7603679..00000000 --- a/example/00-EDB/13_edb_create_component.py +++ /dev/null @@ -1,253 +0,0 @@ -# # EDB: Layout Creation and Setup -# -# This example demonstrates how to to -# -# 1. Create a layout layer stackup. -# 2. Define padstacks. -# 3. Place padstack instances in the layout where the connectors are located. -# 4. Create primitives such as polygons and traces. -# 5. Create "components" from the padstack definitions using "pins". -# >The "component" in EDB acts as a placeholder to enable automatic -# >placement of electrical models, or -# >as in this example to assign ports. In many -# >cases the EDB is imported from a 3rd party layout, in which case the -# >concept of a "component" as a placeholder is needed to map -# >models to the components on the PCB for later use in the -# >simulation. -# 7. Create the HFSS simulation setup and assign ports where the connectors are located. - -# ## View PCB trace model -# -# Here is an image of the model that is created in this example. -# -# -# -# The rectangular sheets at each end of the PCB enable placement of ports where the connectors -# are located. - -# Initialize the EDB layout object. - -# + -import os -import tempfile - -from example.constants import EDB_VERSION -import pyaedt -from pyaedt import Edb - -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -aedb_path = os.path.join(temp_dir.name, "component_example.aedb") - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = Edb(edbpath=aedb_path, edbversion=edb_version) -print("EDB is located at {}".format(aedb_path)) -# - - -# Initialize variables - -layout_count = 12 -diel_material_name = "FR4_epoxy" -diel_thickness = "0.15mm" -cond_thickness_outer = "0.05mm" -cond_thickness_inner = "0.017mm" -soldermask_thickness = "0.05mm" -trace_in_layer = "TOP" -trace_out_layer = "L10" -trace_width = "200um" -connector_size = 2e-3 -conectors_position = [[0, 0], [10e-3, 0]] - -# Create the stackup - -edb.stackup.create_symmetric_stackup( - layer_count=layout_count, - inner_layer_thickness=cond_thickness_inner, - outer_layer_thickness=cond_thickness_outer, - soldermask_thickness=soldermask_thickness, - dielectric_thickness=diel_thickness, - dielectric_material=diel_material_name, -) - -# Create ground planes - -ground_layers = [ - layer_name - for layer_name in edb.stackup.signal_layers.keys() - if layer_name not in [trace_in_layer, trace_out_layer] -] -plane_shape = edb.modeler.Shape("rectangle", pointA=["-3mm", "-3mm"], pointB=["13mm", "3mm"]) -for i in ground_layers: - edb.modeler.create_polygon(plane_shape, i, net_name="VSS") - -# ### Add design parameters -# -# Parameters that are preceded by a _"$"_ character have project-wide scope. -# Therefore, the padstack **definition** and hence all instances of that padstack -# rely on the parameters. -# -# Parameters such as _"trace_in_width"_ and _"trace_out_width"_ have local scope and -# are only used in in the design. - -edb.add_design_variable("$via_hole_size", "0.3mm") -edb.add_design_variable("$antipaddiam", "0.7mm") -edb.add_design_variable("$paddiam", "0.5mm") -edb.add_design_variable("trace_in_width", "0.2mm", is_parameter=True) -edb.add_design_variable("trace_out_width", "0.1mm", is_parameter=True) - -# ### Create the connector component -# -# The component definition is used to place the connector on the PCB. First define the padstacks. - -edb.padstacks.create_padstack( - padstackname="Via", holediam="$via_hole_size", antipaddiam="$antipaddiam", paddiam="$paddiam" -) - -# Create the first connector - -component1_pins = [ - edb.padstacks.place_padstack( - conectors_position[0], - "Via", - net_name="VDD", - fromlayer=trace_in_layer, - tolayer=trace_out_layer, - ), - edb.padstacks.place_padstack( - [ - conectors_position[0][0] - connector_size / 2, - conectors_position[0][1] - connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[0][0] + connector_size / 2, - conectors_position[0][1] - connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[0][0] + connector_size / 2, - conectors_position[0][1] + connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[0][0] - connector_size / 2, - conectors_position[0][1] + connector_size / 2, - ], - "Via", - net_name="VSS", - ), -] - -# Create the second connector - -component2_pins = [ - edb.padstacks.place_padstack( - conectors_position[-1], - "Via", - net_name="VDD", - fromlayer=trace_in_layer, - tolayer=trace_out_layer, - ), - edb.padstacks.place_padstack( - [ - conectors_position[1][0] - connector_size / 2, - conectors_position[1][1] - connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[1][0] + connector_size / 2, - conectors_position[1][1] - connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[1][0] + connector_size / 2, - conectors_position[1][1] + connector_size / 2, - ], - "Via", - net_name="VSS", - ), - edb.padstacks.place_padstack( - [ - conectors_position[1][0] - connector_size / 2, - conectors_position[1][1] + connector_size / 2, - ], - "Via", - net_name="VSS", - ), -] - -# ### Define pins -# -# Pins are fist defined to allow a component to subsequently connect to the remainder -# of the model. In this case, ports are assigned at the connector instances using the pins. - -for padstack_instance in list(edb.padstacks.instances.values()): - padstack_instance.is_pin = True - -# Create components from the pins - -edb.components.create(component1_pins, "connector_1") -edb.components.create(component2_pins, "connector_2") - -# Create ports on the pins and insert a simulation setup using the -# ``SimulationConfiguration`` class. - -sim_setup = edb.new_simulation_configuration() -sim_setup.solver_type = sim_setup.SOLVER_TYPE.Hfss3dLayout -sim_setup.batch_solve_settings.cutout_subdesign_expansion = 0.01 -sim_setup.batch_solve_settings.do_cutout_subdesign = False -sim_setup.batch_solve_settings.signal_nets = ["VDD"] -sim_setup.batch_solve_settings.components = ["connector_1", "connector_2"] -sim_setup.batch_solve_settings.power_nets = ["VSS"] -sim_setup.ac_settings.start_freq = "0GHz" -sim_setup.ac_settings.stop_freq = "5GHz" -sim_setup.ac_settings.step_freq = "1GHz" -edb.build_simulation_project(sim_setup) - -# Save the EDB and open it in the 3D Layout editor. If ``non_graphical==False``, -# there may be a delay while AEDT starts. - -edb.save_edb() -edb.close_edb() -h3d = pyaedt.Hfss3dLayout( - specified_version="2023.2", - projectname=aedb_path, - non_graphical=False, # Set non_graphical = False to launch AEDT in graphical mode. - new_desktop_session=True, -) - -# ### Release the application from the Python kernel -# -# It is important to release the application from the Python kernel after -# execution of the script. The default behavior of the ``release_desktop()`` method closes all open -# projects and closes the application. -# -# If you want to conintue working on the project in graphical mode -# after script execution, call the following method with both arguments set to ``False``. - -h3d.release_desktop(close_projects=True, close_desktop=True) - -# ### Clean up the temporary directory -# -# The following command cleans up the temporary directory, thereby removing all -# project files. If you'd like to save this project, save it to a folder of your choice -# prior to running the following cell. - -temp_dir.cleanup() diff --git a/example/00-EDB/14_edb_create_parametrized_design.py b/example/00-EDB/14_edb_create_parametrized_design.py deleted file mode 100644 index 2a59ac7a..00000000 --- a/example/00-EDB/14_edb_create_parametrized_design.py +++ /dev/null @@ -1,113 +0,0 @@ -# # EDB: parameterized design -# -# This example shows how to -# 1. Set up an HFSS project using SimulationConfiguration class. -# 2. Create automatically parametrized design. -# -# This image shows the layout created in this example: -# -# -# - -# ## Import dependencies. - -import tempfile - -from example.constants import EDB_VERSION -import pyaedt - -# ## Create an instance of a pyaedt.Edb object. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -target_aedb = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) -print("Project is located in ", target_aedb) - -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edb = pyaedt.Edb(edbpath=target_aedb, edbversion=edb_version) -print("AEDB file is located in {}".format(target_aedb)) -# - - -# ## Prepare the layout for the simulation -# -# The ``new_simulation_configuration()`` method creates an instance of -# the ``SimulationConfiguration`` class. This class helps define all preprocessing steps -# required to set up the PCB for simulation. After the simulation configuration has been defined, -# they are applied to the EDB using the ``Edb.build_simulation()`` method. - -simulation_configuration = edb.new_simulation_configuration() -simulation_configuration.signal_nets = [ - "PCIe_Gen4_RX0_P", - "PCIe_Gen4_RX0_N", - "PCIe_Gen4_RX1_P", - "PCIe_Gen4_RX1_N", -] -simulation_configuration.power_nets = ["GND"] -simulation_configuration.components = ["X1", "U1"] -simulation_configuration.do_cutout_subdesign = True -simulation_configuration.start_freq = "OGHz" -simulation_configuration.stop_freq = "20GHz" -simulation_configuration.step_freq = "10MHz" - -# Now apply the simulation setup to the EDB. - -edb.build_simulation_project(simulation_configuration) - -# ## Parameterize -# -# The layout can automatically be set up to enable parametric studies. For example, the -# impact of antipad diameter or trace width on signal integrity performance may be invested -# parametrically. - -edb.auto_parametrize_design( - layers=True, materials=True, via_holes=True, pads=True, antipads=True, traces=True -) -edb.save_edb() -edb.close_edb() - -# ## Open project in AEDT -# -# All manipulations thus far have been executed using the EDB API, which provides fast, -# streamlined processing of layout data in non-graphical mode. The layout and simulation -# setup can be visualized by opening it using the 3D Layout editor in AEDT. -# -# Note that there may be some delay while AEDT is being launched. - -hfss = pyaedt.Hfss3dLayout( - projectname=target_aedb, - specified_version=edb_version, - non_graphical=False, - new_desktop_session=True, -) - -# The following cell can be used to ensure that the design is valid for simulation. - -validation_info = hfss.validate_full_design() -is_ready_to_simulate = True - -# + -for s in validation_info[0]: - if "error" in s: - print(s) - is_ready_to_simulate = False - -if is_ready_to_simulate: - print("The model is ready for simulation.") -else: - print("There are errors in the model that must be fixed.") -# - - -# ## Release the application from the Python kernel -# -# It is important to release the application from the Python kernel after -# execution of the script. The default behavior of the ``release_desktop()`` method closes all open -# projects and closes the application. -# -# If you want to continue working on the project in graphical mode -# after script execution, call the following method with both arguments set to ``False``. - -hfss.release_desktop(close_projects=True, close_desktop=True) -temp_dir.cleanup() # Remove the temporary folder and files. All data will be removd! diff --git a/example/00-EDB/15_ac_analysis.py b/example/00-EDB/15_ac_analysis.py deleted file mode 100644 index 2db9a866..00000000 --- a/example/00-EDB/15_ac_analysis.py +++ /dev/null @@ -1,179 +0,0 @@ -# # EDB: Network Analysis in SIwave -# -# This example shows how to use PyAEDT to set up SYZ analysis on a -# [serdes](https://en.wikipedia.org/wiki/SerDes) channel. -# The signal input is applied differetially. The positive net is _"PCIe_Gen4_TX3_CAP_P"_. -# The negative net is _"PCIe_Gen4_TX3_CAP_N"_. In this example, ports are placed on the -# driver and -# receiver components. - -# ### Perform required imports -# -# Perform required imports, which includes importing a section. - -import tempfile -import time - -from example.constants import EDB_VERSION -import pyaedt - -# ### Download file -# -# Download the AEDB file and copy it in the temporary folder. - -# + -temp_dir = tempfile.TemporaryDirectory(suffix=".ansys") -edb_full_path = pyaedt.downloads.download_file("edb/ANSYS-HSD_V1.aedb", destination=temp_dir.name) -time.sleep(5) - -print(edb_full_path) -# - - -# ### Configure EDB -# -# Create an instance of the ``pyaedt.Edb`` class. - -# + -# Select EDB version (change it manually if needed, e.g. "2023.2") -edb_version = EDB_VERSION -print(f"EDB version: {edb_version}") - -edbapp = pyaedt.Edb(edbpath=edb_full_path, edbversion=edb_version) -# - - -# ### Generate extended nets -# -# An extended net consists of two nets that are connected -# through a passive component such as a resistor or capacitor. - -all_nets = edbapp.extended_nets.auto_identify_signal( - resistor_below=10, inductor_below=1, capacitor_above=1e-9 -) - -# Review the properties of extended nets. - -# + -diff_p = edbapp.nets["PCIe_Gen4_TX3_CAP_P"] -diff_n = edbapp.nets["PCIe_Gen4_TX3_CAP_N"] - -nets_p = list(diff_p.extended_net.nets.keys()) -nets_n = list(diff_n.extended_net.nets.keys()) - -comp_p = list(diff_p.extended_net.components.keys()) -comp_n = list(diff_n.extended_net.components.keys()) - -rlc_p = list(diff_p.extended_net.rlc.keys()) -rlc_n = list(diff_n.extended_net.rlc.keys()) - -print(comp_p, rlc_p, comp_n, rlc_n, sep="\n") -# - - -# Prepare input data for port creation. - -# + -ports = [] -for net_name, net_obj in diff_p.extended_net.nets.items(): - for comp_name, comp_obj in net_obj.components.items(): - if comp_obj.type not in ["Resistor", "Capacitor", "Inductor"]: - ports.append( - { - "port_name": "{}_{}".format(comp_name, net_name), - "comp_name": comp_name, - "net_name": net_name, - } - ) - -for net_name, net_obj in diff_n.extended_net.nets.items(): - for comp_name, comp_obj in net_obj.components.items(): - if comp_obj.type not in ["Resistor", "Capacitor", "Inductor"]: - ports.append( - { - "port_name": "{}_{}".format(comp_name, net_name), - "comp_name": comp_name, - "net_name": net_name, - } - ) - -print(*ports, sep="\n") -# - - -# ### Create ports -# -# Solder balls are generated automatically. The default port type is coax port. - -for d in ports: - port_name = d["port_name"] - comp_name = d["comp_name"] - net_name = d["net_name"] - edbapp.components.create_port_on_component( - component=comp_name, net_list=net_name, port_name=port_name - ) - -# ### Cutout -# -# Retain only relevant parts of the layout. - -nets = [] -nets.extend(nets_p) -nets.extend(nets_n) -edbapp.cutout(signal_list=nets, reference_list=["GND"], extent_type="Bounding") - -# Set up the model for network analysis in SIwave. - -setup = edbapp.create_siwave_syz_setup("setup1") -setup.add_frequency_sweep( - frequency_sweep=[ - ["linear count", "0", "1kHz", 1], - ["log scale", "1kHz", "0.1GHz", 10], - ["linear scale", "0.1GHz", "10GHz", "0.1GHz"], - ] -) - -# Save and close the EDB. - -edbapp.save() -edbapp.close_edb() - -# ### Launch Hfss3dLayout -# -# The HFSS 3D Layout user interface in AEDT is used to import the EDB and -# run the analysis. AEDT 3D Layout can be used to view the model -# if it is launched in graphical mode. - -h3d = pyaedt.Hfss3dLayout( - edb_full_path, - specified_version="2023.2", - non_graphical=False, # Set to true for non-graphical mode. - new_desktop_session=True, -) - -# Define the differential pair. - -h3d.set_differential_pair( - positive_terminal="U1_PCIe_Gen4_TX3_CAP_P", - negative_terminal="U1_PCIe_Gen4_TX3_CAP_N", - diff_name="PAIR_U1", -) -h3d.set_differential_pair( - positive_terminal="X1_PCIe_Gen4_TX3_P", - negative_terminal="X1_PCIe_Gen4_TX3_N", - diff_name="PAIR_X1", -) - -# Solve and plot the results. - -h3d.analyze(num_cores=4) - -# Visualze the results. - -h3d.post.create_report("dB(S(PAIR_U1,PAIR_U1))", context="Differential Pairs") - -# Close AEDT. - -h3d.save_project() -print("Project is saved to {}".format(h3d.project_path)) -h3d.release_desktop(True, True) - -# The following cell cleans up the temporary directory and removes all project data. - -temp_dir.cleanup()