Skip to content

Commit

Permalink
Added set_spice_model method to Hfss3dLayout (#803)
Browse files Browse the repository at this point in the history
* Added set_spice_model method to Hfss3dLayout

* Added set_spice_model method to Hfss3dLayout
  • Loading branch information
maxcapodi78 authored Feb 3, 2022
1 parent 3303389 commit 887d895
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
*----------------------------------------------------------------------
* SPICE Model generated by Murata Manufacturing Co., Ltd.
* Copyright(C) Murata Manufacturing Co., Ltd.
* Description :3225M(1210)/X7R/2.2uF/100V
* Murata P/N :GRM32ER72A225KA35
* Property : C = 2.2[uF]
* Data Generated on Mar 14, 2018
*----------------------------------------------------------------------
* Applicable Conditions:
* Frequency Range = 100Hz-6GHz
* Temperature = 25 degC
* DC Bias Voltage = 0V
* Small Signal Operation
*----------------------------------------------------------------------
.SUBCKT GRM32ER72A225KA35_25C_0V port1 port2
C1 port1 11 2.18e-6
L2 11 12 1.28e-10
R3 12 13 2.50e-3
C4 13 14 8.43e-5
R4 13 14 91.0
C5 14 15 3.62e-4
R5 14 15 1.44
C6 15 16 2.76e-4
R6 15 16 1.91e-1
C7 16 17 2.39e-4
R7 16 17 2.22e-2
C8 17 18 1.82e-4
R8 17 18 2.69e-3
L9 18 19 3.18e-10
R9 18 19 3.02e-2
L10 19 20 1.76e-11
R10 19 20 2.18e-2
C11 20 21 4.33e-6
L11 20 21 1.35e-10
R11 20 21 3.50e-2
C12 21 22 2.64e-6
L12 21 22 7.74e-11
R12 21 22 1.86e-2
C13 22 port2 1.81e-12
L13 22 port2 2.74e-10
R13 22 port2 46.5
R100 port1 11 2.27e+8
.ENDS GRM32ER72A225KA35_25C_0V
6 changes: 6 additions & 0 deletions _unittest/test_40_3dlayout_edb.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,9 @@ def test_04_add_mesh_operations(self):

def test_05_change_property(self):
assert self.aedtapp.modeler.change_property("Excitations:J2B3-2", "Impedance", "49ohm", "EM Design")

def test_06_assign_spice_model(self):
model_path = os.path.join(self.local_scratch.path, test_project_name + ".aedb", "GRM32ER72A225KA35_25C_0V.sp")
assert self.aedtapp.modeler.set_spice_model(
component_name="C3A3", model_path=model_path, subcircuit_name="GRM32ER72A225KA35_25C_0V"
)
2 changes: 1 addition & 1 deletion pyaedt/application/Analysis3DLayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def __init__(
self._oboundary = self._odesign.GetModule("Excitations")
self.logger.info("Analysis Loaded")
self._modeler = Modeler3DLayout(self)
self._modeler.primitives.init_padstacks()
self._modeler.init_padstacks()
self.logger.info("Modeler Loaded")
self._mesh = Mesh3d(self)
self._post = PostProcessor(self)
Expand Down
7 changes: 5 additions & 2 deletions pyaedt/application/Design.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,9 +973,12 @@ def oproject(self, proj_name=None):
time.sleep(0.5)
proj = self.odesktop.GetActiveProject()
self.logger.info("Archive {} has been restored to project {}".format(proj_name, proj.GetName()))
elif ".def" in proj_name:
elif ".def" in proj_name or proj_name[-5:] == ".aedb":
oTool = self.odesktop.GetTool("ImportExport")
oTool.ImportEDB(proj_name)
if ".def" in proj_name:
oTool.ImportEDB(proj_name)
else:
oTool.ImportEDB(os.path.join(proj_name, "edb.def"))
proj = self.odesktop.GetActiveProject()
proj.Save()
self.logger.info("EDB folder %s has been imported to project %s", proj_name, proj.GetName())
Expand Down
3 changes: 2 additions & 1 deletion pyaedt/hfss3dlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ class Hfss3dLayout(FieldAnalysis3DLayout):
----------
projectname : str, optional
Name of the project to select or the full path to the project
or AEDTZ archive to open. The default is ``None``, in which
or AEDTZ archive to open or the path to aedb folder or edb.def file.
The default is ``None``, in which
case an attempt is made to get an active project. If no
projects are present, an empty project is created.
designname : str, optional
Expand Down
115 changes: 114 additions & 1 deletion pyaedt/modeler/Model3DLayout.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import time
import re
from warnings import warn

from pyaedt.generic.constants import AEDT_UNITS
Expand All @@ -10,6 +11,7 @@
is_ironpython,
_pythonver,
inside_desktop,
get_filename_without_extension,
)
from pyaedt.modules.LayerStackup import Layers
from pyaedt.modeler.Modeler import Modeler
Expand Down Expand Up @@ -68,7 +70,9 @@ def __init__(self, app):

self.logger.info("Primitives loaded.")
self.layers.refresh_all_layers()

self.o_def_manager = self._app.odefinition_manager
self.o_component_manager = self.o_def_manager.GetManager("Component")
self.o_model_manager = self.o_def_manager.GetManager("Model")
pass

@property
Expand Down Expand Up @@ -669,3 +673,112 @@ def set_temperature_dependence(
else:
self.logger.info("Assigned Objects Temperature")
return True

@aedt_exception_handler
def set_spice_model(self, component_name, model_path, model_name=None, subcircuit_name=None, pin_map=None):
"""Assign a Spice model to a component.
Parameters
----------
component_name : str
Name of the component.
model_path : str, optional
Full path to the model file. The default is ``None``.
model_name : str, optional
Name of the model. The default is ``None`` which means that model_name is file name without extension.
subcircuit_name : str, optional
Name of the subcircuit. The default is ``None`` which means that subcircuit name is the model_name.
pin_map : list, optional
List of [spice_pin_name, aedt_pin_name] to optional
customize the pin mapping between Spice Pins and AEDT Pins.
Returns
-------
bool
``True`` when successful, ``False`` when failed.
Examples
--------
>>> from pyaedt import Hfss3dLayout
>>> h3d = Hfss3dLayout("myproject")
>>> h3d.modeler.set_spice_model(component_name="A1",
... modelpath="pathtospfile",
... modelname="spicemodelname",
... subcircuit_name="SUBCK1")
"""
if not model_name:
model_name = get_filename_without_extension(model_path)
if model_name not in list(self.o_model_manager.GetNames()):
args = [
"NAME:" + model_name,
"Name:=",
model_name,
"ModTime:=",
1643711258,
"Library:=",
"",
"LibLocation:=",
"Project",
"ModelType:=",
"dcirspice",
"Description:=",
"",
"ImageFile:=",
"",
"SymbolPinConfiguration:=",
0,
["NAME:PortInfoBlk"],
["NAME:PortOrderBlk"],
"filename:=",
model_path,
"modelname:=",
model_name,
]
self.o_model_manager.Add(args)
if not subcircuit_name:
subcircuit_name = model_name
with open(model_path, "r") as f:
for line in f:
if "subckt" in line.lower():
pinNames = [i.strip() for i in re.split(" |\t", line) if i]
pinNames.remove(pinNames[0])
pinNames.remove(pinNames[0])
break
componentPins = [i.GetName() for i in self.edb.core_components.get_pin_from_component(component_name)]
componentPins.reverse()
if not pin_map:
pin_map = []
i = 0
if len(componentPins) >= len(pinNames):
for pn in pinNames:
pin_map.append(pn + ":=")
pin_map.append(componentPins[i])
i += 1
args2 = [
"CompPropEnabled:=",
True,
"Pid:=",
-1,
"Pmo:=",
"0",
"CompPropType:=",
0,
"PinPairRLC:=",
[
"RLCModelType:=",
4,
"SPICE_file_path:=",
model_path,
"SPICE_model_name:=",
model_name,
"SPICE_subckt:=",
subcircuit_name,
"terminal_pin_map:=",
pin_map,
],
]
args = ["NAME:ModelChanges", ["NAME:UpdateModel0", ["NAME:ComponentNames", component_name], "Prop:=", args2]]
self.oeditor.UpdateModels(args)
self.logger.info("Spice Model Correctly assigned to {}.".format(component_name))
return True

0 comments on commit 887d895

Please sign in to comment.