Download this example
Download this example as a Jupyter Notebook or as a Python script.
PCB DCIR analysis#
This example shows how to use PyAEDT to create a design in Q3D Extractor and run a DC IR drop simulation starting from an EDB project.
Keywords: Q3D, layout, DCIR.
Perform imports and define constants#
Perform required imports.
[1]:
import os
import tempfile
import time
import ansys.aedt.core
import pyedb
from ansys.aedt.core.examples.downloads import download_file
from ansys.aedt.core.generic.constants import Axis, Plane
Define constants.
[2]:
AEDT_VERSION = "2026.1"
NUM_CORES = 4
NG_MODE = False
Create temporary directory#
Create a temporary directory where downloaded data or dumped data can be stored. If you’d like to retrieve the project data for subsequent use, the temporary folder name is given by temp_folder.name.
[3]:
temp_folder = tempfile.TemporaryDirectory(suffix=".ansys")
# ## Set up project files and path
#
# Download needed project file and set up temporary project directory.
[4]:
aedb_project = download_file("edb/ANSYS-HSD_V1.aedb", local_path=temp_folder.name)
coil = download_file(
source="inductance_3d_component",
name="air_coil.a3dcomp",
local_path=temp_folder.name,
)
res = download_file(source="resistors", name="Res_0402.a3dcomp", local_path=temp_folder.name)
project_name = "HSD"
output_edb = os.path.join(temp_folder.name, project_name + ".aedb")
output_q3d = os.path.join(temp_folder.name, project_name + "_q3d.aedt")
Open EDB project#
Open the EDB project and create a cutout on the selected nets before exporting to Q3D.
[5]:
edb = pyedb.Edb(edbpath=aedb_project, version=AEDT_VERSION)
signal_nets = ["1.2V_AVDLL_PLL", "1.2V_AVDDL", "1.2V_DVDDL", "NetR106_1"]
ground_nets = ["GND"]
cutout_points = edb.cutout(signal_nets=signal_nets, reference_nets=ground_nets, output_aedb_path=output_edb)
C:\actions-runner\_work\pyaedt-examples\pyaedt-examples\.venv\lib\site-packages\pyedb\generic\design_types.py:375: UserWarning: You are using PyEDB with grpc, which is currently in beta. Some feature might be missing or not working as expected. Please report any issue you find to the PyEDB team.
warnings.warn(GRPC_BETA_WARNING, UserWarning)
PyEDB INFO: Logger is initialized in EDB.
PyEDB INFO: legacy v0.75.0
PyEDB INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyEDB INFO: Using PyEDB with gRPC as Beta until ANSYS 2027R1 official release.
PyEDB INFO: Logger is initialized in EDB.
PyEDB INFO: legacy v0.75.0
PyEDB INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyEDB INFO: Grpc session started
PyEDB INFO: Grpc session started: pid=12212
PyEDB INFO: RPC session acquired (open databases: 1)
PyEDB INFO: Database ANSYS-HSD_V1.aedb Opened in 2026.1
PyEDB INFO: Cell main Opened
PyEDB INFO: Refreshing the Components dictionary.
PyEDB INFO: Builder was initialized.
PyEDB INFO: EDB initialized.
PyEDB INFO: -----------------------------------------
PyEDB INFO: Trying cutout with 2.0mm expansion size
PyEDB INFO: -----------------------------------------
PyEDB INFO: GRPC cut-out started
PyEDB INFO: [READ] Data collection finished in 3.053 s
PyEDB INFO: Nets:348, padstack_instances:5699, primitives:2107, components:509
PyEDB INFO: [EXTENT] Polygon created in 0.652 s
PyEDB INFO: [COMPUTE] Decision lists ready in 20.929 s
PyEDB INFO: Starting single write-pass
PyEDB INFO: Deleting 343 nets
PyEDB INFO: 5601 pad-stack instances deleted in 0.142 s
PyEDB INFO: 3813 primitives deleted in 0.108 s
PyEDB INFO: 11 primitives created in 0.230 s
C:\actions-runner\_work\pyaedt-examples\pyaedt-examples\.venv\lib\site-packages\pyedb\workflows\utilities\cutout.py:778: FutureWarning: Accessing deprecated property numpins. use num_pins property instead
components_to_delete = [comp for comp in all_components if comp.numpins == 0]
PyEDB INFO: 486 components deleted in 0.785 s
PyEDB INFO: Refreshing the Components dictionary.
PyEDB INFO: [WRITE] All writes finished in 3.824 s
PyEDB INFO: GRPC-safe cut-out completed Elapsed time: 0m 29sec
PyEDB INFO: Cutout completed in 1 iterations with expansion size of 2.0mm Elapsed time: 0m 29sec
Identify pin positions#
Identify [x,y] pin locations on the components to define where to assign sources and sinks for Q3D.
[6]:
pin_u11_scl = [i for i in edb.components["U11"].pins.values() if i.net_name == "1.2V_AVDLL_PLL"]
pin_u9_1 = [i for i in edb.components["U9"].pins.values() if i.net_name == "1.2V_AVDDL"]
pin_u9_2 = [i for i in edb.components["U9"].pins.values() if i.net_name == "1.2V_DVDDL"]
pin_u11_r106 = [i for i in edb.components["U11"].pins.values() if i.net_name == "NetR106_1"]
Append Z Positions#
Compute the Q3D 3D position. The units in EDB are meters so the factor 1000 converts from meters to millimeters.
[7]:
location_u11_scl = [i * 1000 for i in pin_u11_scl[0].position]
location_u11_scl.append(edb.components["U11"].upper_elevation * 1000)
location_u9_1_scl = [i * 1000 for i in pin_u9_1[0].position]
location_u9_1_scl.append(edb.components["U9"].upper_elevation * 1000)
location_u9_2_scl = [i * 1000 for i in pin_u9_2[0].position]
location_u9_2_scl.append(edb.components["U9"].upper_elevation * 1000)
location_u11_r106 = [i * 1000 for i in pin_u11_r106[0].position]
location_u11_r106.append(edb.components["U11"].upper_elevation * 1000)
Identify pin positions for 3D components#
Identify the pin positions where 3D components of passives are to be added.
[8]:
location_l2_1 = [i * 1000 for i in edb.components["L2"].pins["1"].position]
location_l2_1.append(edb.components["L2"].upper_elevation * 1000)
location_l4_1 = [i * 1000 for i in edb.components["L4"].pins["1"].position]
location_l4_1.append(edb.components["L4"].upper_elevation * 1000)
location_r106_1 = [i * 1000 for i in edb.components["R106"].pins["1"].position]
location_r106_1.append(edb.components["R106"].upper_elevation * 1000)
Save and close EDB#
Save and close EDB. Then, open EDT in HFSS 3D Layout to generate the 3D model.
[9]:
edb.save()
edb.close()
time.sleep(3)
h3d = ansys.aedt.core.Hfss3dLayout(output_edb, version=AEDT_VERSION, non_graphical=NG_MODE, new_desktop=True)
PyEDB INFO: RPC session released (open databases: 0)
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)].
PyAEDT INFO: PyAEDT version 1.0.dev0.
PyAEDT INFO: Initializing new Desktop session.
PyAEDT INFO: AEDT version 2026.1.
PyAEDT INFO: New AEDT session is starting on gRPC port 50533.
PyAEDT INFO: Starting new AEDT gRPC session on port 50533.
PyAEDT INFO: Launching AEDT server with gRPC transport mode: wnua
PyAEDT INFO: Electronics Desktop started on gRPC port 50533 after 10.2 seconds.
PyAEDT INFO: AEDT installation Path C:\Program Files\ANSYS Inc\v261\AnsysEM
PyAEDT INFO: Connected to AEDT gRPC session on port 50533.
PyAEDT INFO: Non-graphical mode detected. Disabling Desktop logs.
PyAEDT INFO: EDB folder C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD.aedb has been imported to project HSD
PyAEDT INFO: Active Design set to 0;main
PyAEDT INFO: AEDT objects correctly read
Export to Q3D#
Create a dummy setup and export the layout to Q3D. The keep_net_name parameter reassigns Q3D net names from HFSS 3D Layout.
[10]:
setup = h3d.create_setup()
setup.export_to_q3d(output_q3d, keep_net_name=True)
h3d.close_project()
time.sleep(3)
PyAEDT INFO: Project: HSD, Design: main, [info] Translation Info: Export complete (00:00:04). (08:20:11 AM May 16, 2026)
PyAEDT INFO: Project: HSD, Design: main, [info] File written to C:/Users/ansys/AppData/Local/Temp/tmpu0tselve.ansys/HSD_q3d.aedt. (08:20:11 AM May 16, 2026)
PyAEDT INFO: Loading Modeler.
PyAEDT INFO: Modeler loaded.
PyAEDT INFO: Modeler class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: No EDB gRPC setting provided. Enabling gRPC for EDB.
PyAEDT INFO: Loading EDB with Grpc enabled.
PyEDB INFO: Logger is initialized in EDB.
PyEDB INFO: legacy v0.75.0
PyEDB INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyEDB INFO: Using PyEDB with gRPC as Beta until ANSYS 2027R1 official release.
PyEDB WARNING: AEDT project-related file C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD.aedt exists and may need to be deleted before opening the EDB in HFSS 3D Layout.
PyEDB WARNING: AEDT project-related file C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD.aedt.lock exists and may need to be deleted before opening the EDB in HFSS 3D Layout.
PyEDB INFO: Logger is initialized in EDB.
PyEDB INFO: legacy v0.75.0
PyEDB INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyEDB INFO: Grpc session started
PyEDB INFO: Grpc session started: pid=12188
PyEDB INFO: RPC session acquired (open databases: 1)
PyEDB INFO: Database HSD.aedb Opened in 2026.1
PyEDB INFO: Cell main Opened
PyEDB INFO: Refreshing the Components dictionary.
PyEDB INFO: Builder was initialized.
PyEDB INFO: EDB initialized.
PyAEDT INFO: Processing net NetR106_1...
PyAEDT INFO: Processing net GND...
PyAEDT INFO: Processing net 1.2V_DVDDL...
PyAEDT INFO: Processing net 1.2V_AVDLL_PLL...
PyAEDT INFO: Processing net 1.2V_AVDDL...
PyAEDT INFO: Net processing completed.
PyAEDT INFO: Processing vias...
PyAEDT INFO: Vias processing completed.
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)].
PyAEDT INFO: Parsing C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD_q3d.aedt.
PyAEDT INFO: PyAEDT version 1.0.dev0.
PyAEDT INFO: Returning found Desktop session with PID 7824!
PyAEDT INFO: File C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD_q3d.aedt correctly loaded. Elapsed time: 0m 0sec
PyAEDT INFO: Project HSD_q3d has been opened.
PyAEDT INFO: Active Design set to Q3DDesign1
PyAEDT INFO: AEDT objects correctly read
PyAEDT INFO: Modeler class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: Materials class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: Renaming primitives for net NetR106_1...
PyAEDT INFO: Renaming primitives for net GND...
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Union of 51 objects has been executed.
PyAEDT INFO: Renaming primitives for net 1_2V_DVDDL...
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Union of 12 objects has been executed.
PyAEDT INFO: Renaming primitives for net 1_2V_AVDLL_PLL...
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Union of 5 objects has been executed.
PyAEDT INFO: Renaming primitives for net 1_2V_AVDDL...
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Union of 5 objects has been executed.
PyAEDT INFO: 1 Nets have been identified: GND_1
PyAEDT INFO: Closing the AEDT Project HSD_q3d
PyAEDT INFO: Project HSD_q3d closed correctly
PyEDB INFO: RPC session released (open databases: 0)
PyAEDT INFO: Closing the AEDT Project HSD
PyAEDT INFO: Project HSD closed correctly
Open Q3D#
Launch the newly created Q3D project.
[11]:
q3d = ansys.aedt.core.Q3d(output_q3d, version=AEDT_VERSION)
q3d.modeler.delete("GND")
q3d.modeler.delete("16_Bottom_L6")
q3d.delete_all_nets()
PyAEDT INFO: Parsing C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD_q3d.aedt.
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr 5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)].
PyAEDT INFO: PyAEDT version 1.0.dev0.
PyAEDT INFO: Returning found Desktop session with PID 7824!
PyAEDT INFO: File C:\Users\ansys\AppData\Local\Temp\tmpu0tselve.ansys\HSD_q3d.aedt correctly loaded. Elapsed time: 0m 0sec
PyAEDT INFO: Project HSD_q3d has been opened.
PyAEDT INFO: Active Design set to Q3DDesign1
PyAEDT INFO: AEDT objects correctly read
PyAEDT INFO: Modeler class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 1 Objects: GND.
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 1 Objects: 16_Bottom_L6.
[11]:
True
Insert inductors#
Create coordinate systems and place 3D component inductors.
[12]:
q3d.modeler.create_coordinate_system(location_l2_1, name="L2")
comp = q3d.modeler.insert_3d_component(coil, coordinate_system="L2")
comp.rotate(Axis.Z, -90)
comp.parameters["n_turns"] = "3"
comp.parameters["d_wire"] = "100um"
q3d.modeler.set_working_coordinate_system("Global")
q3d.modeler.create_coordinate_system(location_l4_1, name="L4")
comp2 = q3d.modeler.insert_3d_component(coil, coordinate_system="L4")
comp2.rotate(Axis.Z, -90)
comp2.parameters["n_turns"] = "3"
comp2.parameters["d_wire"] = "100um"
q3d.modeler.set_working_coordinate_system("Global")
q3d.modeler.set_working_coordinate_system("Global")
q3d.modeler.create_coordinate_system(location_r106_1, name="R106")
comp3 = q3d.modeler.insert_3d_component(res, geometry_parameters={"$Resistance": 2000}, coordinate_system="R106")
comp3.rotate(Axis.Z, -90)
q3d.modeler.set_working_coordinate_system("Global")
[12]:
True
Delete dielectrics#
Delete all dielectric objects since they are not needed in DC analysis.
[13]:
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4"))
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4_2"))
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Megtron4_3"))
q3d.modeler.delete(q3d.modeler.get_objects_by_material("Solder Resist"))
objs_copper = q3d.modeler.get_objects_by_material("copper")
objs_copper_names = [i.name for i in objs_copper]
q3d.plot(
show=False,
assignment=objs_copper_names,
plot_as_separate_objects=False,
output_file=os.path.join(temp_folder.name, "Q3D.jpg"),
plot_air_objects=False,
)
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 4 Objects: DE1,DE3,DE5,DE7.
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 6 Objects: DE2,DE6,Inner1_GND1_t_fill,Inner2_PWR1_t_fill,Inner5_PWR2_t_fill,Inner6_GND2_t_fill.
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 3 Objects: Inner3_Sig1_t_fill,Inner4_Sig2_t_fill,Megtron4_1mm.
PyAEDT INFO: Parsing design objects. This operation can take time
PyAEDT INFO: Refreshing bodies from Object Info
PyAEDT INFO: Bodies Info Refreshed Elapsed time: 0m 0sec
PyAEDT INFO: 3D Modeler objects parsed. Elapsed time: 0m 0sec
PyAEDT INFO: Deleted 2 Objects: 16_Bottom_t_fill,1_Top_t_fill.
PyAEDT INFO: PostProcessor class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: Post class has been initialized! Elapsed time: 0m 0sec
[13]:
Class: ansys.aedt.core.visualization.plot.pyvista.ModelPlotter
Assign source and sink#
Use previously calculated positions to identify faces. Select the net 1_Top and assign sources and sinks on nets.
[14]:
sink_f = q3d.modeler.create_circle(Plane.XY, location_u11_scl, 0.1)
source_f1 = q3d.modeler.create_circle(Plane.XY, location_u9_1_scl, 0.1)
source_f2 = q3d.modeler.create_circle(Plane.XY, location_u9_2_scl, 0.1)
source_f3 = q3d.modeler.create_circle(Plane.XY, location_u11_r106, 0.1)
sources_objs = [source_f1, source_f2, source_f3]
q3d.auto_identify_nets()
identified_net = q3d.net_names[0]
q3d.sink(sink_f, net_name=identified_net)
source1 = q3d.source(source_f1, net_name=identified_net)
source2 = q3d.source(source_f2, net_name=identified_net)
source3 = q3d.source(source_f3, net_name=identified_net)
sources_bounds = [source1, source2, source3]
q3d.edit_sources(
dcrl={
"{}:{}".format(source1.props["Net"], source1.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source2.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source3.name): "-1.0A",
}
)
PyAEDT INFO: Materials class has been initialized! Elapsed time: 0m 0sec
PyAEDT INFO: 1 Nets have been identified: 1_2V_AVDDL
PyAEDT INFO: Boundary Sink Sink_6DOIVI has been created.
PyAEDT INFO: Boundary Source Source_Q5DHRI has been created.
PyAEDT INFO: Boundary Source Source_3Q2CIX has been created.
PyAEDT INFO: Boundary Source Source_7DLDWK has been created.
[14]:
True
Create setup#
Create a setup and a frequency sweep from DC to 2GHz. Then, analyze the project.
[15]:
setup = q3d.create_setup()
setup.dc_enabled = True
setup.capacitance_enabled = False
setup.ac_rl_enabled = False
setup.props["SaveFields"] = True
setup.props["DC"]["Cond"]["MaxPass"] = 3
Solve setup#
[16]:
q3d.save_project()
PyAEDT INFO: Project HSD_q3d Saved correctly
[16]:
True
Create a named expression#
Use PyAEDT advanced fields calculator to add from the expressions catalog the voltage drop.
[17]:
voltage_drop = q3d.post.fields_calculator.add_expression("voltage_drop", None)
Release AEDT#
[18]:
q3d.save_project()
q3d.release_desktop()
# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.
time.sleep(3)
PyAEDT INFO: Project HSD_q3d Saved correctly
PyAEDT INFO: Desktop has been released and closed.
Clean up#
All project files are saved in the folder temp_folder.name. If you’ve run this example as a Jupyter notebook, you can retrieve those project files. The following cell removes all temporary files, including the project folder.
[19]:
temp_folder.cleanup()
Download this example
Download this example as a Jupyter Notebook or as a Python script.