Skip to content

Commit bc6ad8d

Browse files
committed
modify defaults and add double pad elmer sim
1 parent 83c8d09 commit bc6ad8d

20 files changed

+2959
-1
lines changed

klayout_package/python/kqcircuits/defaults.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454

5555
TMP_PATH.mkdir(parents=True, exist_ok=True) # TODO move elsewhere?
5656

57-
ANSYS_EXECUTABLE = find_ansys_executable(r"%PROGRAMFILES%\AnsysEM\v241\Win64\ansysedt.exe")
57+
ANSYS_EXECUTABLE = find_ansys_executable(r"%PROGRAMFILES%\AnsysEM\AnsysEM21.2\Win64\ansysedt.exe")
5858
ANSYS_SCRIPT_PATHS = [
5959
SCRIPTS_PATH.joinpath("simulations").joinpath("ansys"),
6060
SCRIPTS_PATH.joinpath("simulations").joinpath("post_process"),

klayout_package/python/kqcircuits/junctions/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"No Squid",
3232
"Manhattan",
3333
"Manhattan Single Junction",
34+
'Manhattan Single Junction Centered',
3435
#'QCD1',
3536
"Sim",
3637
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# This code is part of KQCircuits
2+
# Copyright (C) 2024 IQM Finland Oy
3+
#
4+
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5+
# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6+
# version.
7+
#
8+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
#
11+
# You should have received a copy of the GNU General Public License along with this program. If not, see
12+
# https://www.gnu.org/licenses/gpl-3.0.html.
13+
#
14+
# The software distribution should follow IQM trademark policy for open-source software
15+
# (meetiqm.com/developers/osstmpolicy). IQM welcomes contributions to the code. Please see our contribution agreements
16+
# for individuals (meetiqm.com/developers/clas/individual) and organizations (meetiqm.com/developers/clas/organization).
17+
"""
18+
Calculates Q-factors from S-parameter results.
19+
For each port creates network where all other ports are terminated by resistor.
20+
The Q-factor of the port is the calculated from y-parameters by imag(y) / real(y),
21+
"""
22+
import json
23+
import os
24+
import sys
25+
import skrf
26+
27+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "util"))
28+
from post_process_helpers import read_snp_network # pylint: disable=wrong-import-position, no-name-in-module
29+
30+
# Find data files
31+
path = os.path.curdir
32+
result_files = [f for f in os.listdir(path) if f[:-2].endswith("_project_SMatrix.s")]
33+
for result_file in result_files:
34+
snp_network, z0s = read_snp_network(result_file)
35+
freq = skrf.Frequency.from_f(snp_network.f)
36+
37+
output_data = {"frequencies": list(freq.f)}
38+
for i, z0 in enumerate(z0s):
39+
port = skrf.Circuit.Port(freq, "port", z0=z0)
40+
connections = [[(snp_network, i), (port, 0)]]
41+
for j, z0j in enumerate(z0s):
42+
if j != i:
43+
resistor = skrf.Circuit.SeriesImpedance(freq, z0j, f"res{j}]")
44+
gnd = skrf.Circuit.Ground(freq, f"gnd{j}")
45+
connections += [[(snp_network, j), (resistor, 0)], [(resistor, 1), (gnd, 0)]]
46+
circ = skrf.Circuit(connections)
47+
q = [y[0][0].imag / y[0][0].real for y in circ.network.y]
48+
if any(v > 0 for v in q): # ignore ports that gets invalid q values
49+
output_data[f"Q_port{i + 1}"] = q
50+
51+
output_file = result_file[:-2].replace("_project_SMatrix.s", "_q.json")
52+
with open(output_file, "w") as f:
53+
json.dump(output_data, f, indent=4)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# This code is part of KQCircuits
2+
# Copyright (C) 2021 IQM Finland Oy
3+
#
4+
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5+
# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6+
# version.
7+
#
8+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
#
11+
# You should have received a copy of the GNU General Public License along with this program. If not, see
12+
# https://www.gnu.org/licenses/gpl-3.0.html.
13+
#
14+
# The software distribution should follow IQM trademark policy for open-source software
15+
# (meetiqm.com/developers/osstmpolicy). IQM welcomes contributions to the code. Please see our contribution agreements
16+
# for individuals (meetiqm.com/developers/clas/individual) and organizations (meetiqm.com/developers/clas/organization).
17+
18+
19+
# This is a Python 2.7 script that should be run in Ansys Electronics Desktop in order to create capacitance matrix
20+
# output variables.
21+
import os
22+
import sys
23+
import time
24+
25+
import ScriptEnv
26+
27+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "util"))
28+
from util import get_enabled_setup, get_enabled_sweep # pylint: disable=wrong-import-position,no-name-in-module
29+
30+
# Set up environment
31+
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
32+
33+
oDesktop.RestoreWindow()
34+
oProject = oDesktop.GetActiveProject()
35+
oDesign = oProject.GetActiveDesign()
36+
oBoundarySetup = oDesign.GetModule("BoundarySetup")
37+
oOutputVariable = oDesign.GetModule("OutputVariable")
38+
39+
40+
oDesktop.AddMessage("", "", 0, "Creating capacitive PI model for all ports (%s)" % time.asctime(time.localtime()))
41+
42+
design_type = oDesign.GetDesignType()
43+
if design_type == "HFSS":
44+
setup = get_enabled_setup(oDesign)
45+
if oDesign.GetSolutionType() == "HFSS Terminal Network":
46+
sweep = get_enabled_sweep(oDesign, setup)
47+
solution = setup + (" : LastAdaptive" if sweep is None else " : " + sweep)
48+
context = [] if sweep is None else ["Domain:=", "Sweep"]
49+
50+
ports = oBoundarySetup.GetExcitations()[::2]
51+
52+
for i, port_i in enumerate(ports):
53+
for j, port_j in enumerate(ports):
54+
# PI model admittance element
55+
if i == j:
56+
# admittance yii between port i and ground
57+
expression = " + ".join(["Yt(%s,%s)" % (port_i, port_k) for port_k in ports])
58+
else:
59+
# admittance yij between port i and j
60+
expression = "-Yt(%s,%s)" % (port_i, port_j)
61+
62+
oOutputVariable.CreateOutputVariable(
63+
"yy_%s_%s" % (port_i, port_j), expression, solution, "Terminal Solution Data", []
64+
)
65+
66+
# Estimate capacitance vs frequency assuming capacitive elements
67+
oOutputVariable.CreateOutputVariable(
68+
"C_%s_%s" % (port_i, port_j),
69+
"im(yy_%s_%s)/(2*pi*Freq)" % (port_i, port_j),
70+
solution,
71+
"Terminal Solution Data",
72+
[],
73+
)
74+
75+
elif design_type == "Q3D Extractor":
76+
setup = get_enabled_setup(oDesign, tab="General")
77+
nets = oBoundarySetup.GetExcitations()[::2]
78+
net_types = oBoundarySetup.GetExcitations()[1::2]
79+
signal_nets = [net for net, net_type in zip(nets, net_types) if net_type == "SignalNet"]
80+
81+
for i, net_i in enumerate(signal_nets):
82+
for j, net_j in enumerate(signal_nets):
83+
if i == j:
84+
expression = " + ".join(["C({},{})".format(net_i, net_k) for net_k in signal_nets])
85+
else:
86+
expression = "-C({},{})".format(net_i, net_j)
87+
88+
oOutputVariable.CreateOutputVariable(
89+
"C_{}_{}".format(net_i, net_j),
90+
expression,
91+
setup + " : LastAdaptive",
92+
"Matrix",
93+
["Context:=", "Original"],
94+
)
95+
96+
# Notify the end of script
97+
oDesktop.AddMessage("", "", 0, "The capacitive PI model created (%s)" % time.asctime(time.localtime()))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# This code is part of KQCircuits
2+
# Copyright (C) 2023 IQM Finland Oy
3+
#
4+
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5+
# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6+
# version.
7+
#
8+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
#
11+
# You should have received a copy of the GNU General Public License along with this program. If not, see
12+
# https://www.gnu.org/licenses/gpl-3.0.html.
13+
#
14+
# The software distribution should follow IQM trademark policy for open-source software
15+
# (meetiqm.com/developers/osstmpolicy). IQM welcomes contributions to the code. Please see our contribution agreements
16+
# for individuals (meetiqm.com/developers/clas/individual) and organizations (meetiqm.com/developers/clas/organization).
17+
18+
19+
# This is a Python 2.7 script that should be run in Ansys Electronics Desktop in order to create reports.
20+
import os
21+
import sys
22+
import time
23+
24+
import ScriptEnv
25+
26+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "util"))
27+
# fmt: off
28+
from util import get_enabled_setup, get_enabled_sweep, create_x_vs_y_plot, get_quantities \
29+
# pylint: disable=wrong-import-position,no-name-in-module
30+
# fmt: on
31+
32+
# Set up environment
33+
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
34+
35+
oDesktop.RestoreWindow()
36+
oProject = oDesktop.GetActiveProject()
37+
oDesign = oProject.GetActiveDesign()
38+
oBoundarySetup = oDesign.GetModule("BoundarySetup")
39+
oOutputVariable = oDesign.GetModule("OutputVariable")
40+
oReportSetup = oDesign.GetModule("ReportSetup")
41+
42+
# Create model separately for HFSS and Q3D
43+
oDesktop.AddMessage("", "", 0, "Creating reports (%s)" % time.asctime(time.localtime()))
44+
45+
design_type = oDesign.GetDesignType()
46+
if design_type == "HFSS":
47+
setup = get_enabled_setup(oDesign)
48+
if oDesign.GetSolutionType() == "HFSS Terminal Network":
49+
sweep = get_enabled_sweep(oDesign, setup)
50+
solution = setup + (" : LastAdaptive" if sweep is None else " : " + sweep)
51+
context = [] if sweep is None else ["Domain:=", "Sweep"]
52+
ports = oBoundarySetup.GetExcitations()[::2]
53+
54+
# Create capacitance vs frequency report
55+
unique_elements_c = [
56+
"C_%s_%s" % (port_i, ports[j]) for i, port_i in enumerate(ports) for j in range(i, len(ports))
57+
] # The unique elements (half matrix), used for plotting C-matrix
58+
unique_output_c = [e for e in unique_elements_c if e in oOutputVariable.GetOutputVariables()]
59+
if unique_output_c:
60+
create_x_vs_y_plot(
61+
oReportSetup,
62+
"Capacitance vs Frequency",
63+
"Terminal Solution Data",
64+
solution,
65+
context,
66+
["Freq:=", ["All"]],
67+
"Freq",
68+
"C [fF]",
69+
unique_output_c,
70+
)
71+
72+
# Create S vs frequency and S convergence reports
73+
unique_elements_s = [
74+
"St(%s,%s)" % (port_i, ports[j]) for i, port_i in enumerate(ports) for j in range(i, len(ports))
75+
] # The unique elements (half matrix), used for plotting S-matrix
76+
unique_output_s = [
77+
"dB(%s)" % e
78+
for e in unique_elements_s
79+
if e in get_quantities(oReportSetup, "Terminal Solution Data", solution, context, "Terminal S Parameter")
80+
]
81+
if unique_output_s:
82+
create_x_vs_y_plot(
83+
oReportSetup,
84+
"S vs Frequency",
85+
"Terminal Solution Data",
86+
solution,
87+
context,
88+
["Freq:=", ["All"]],
89+
"Freq",
90+
"S [dB]",
91+
unique_output_s,
92+
)
93+
create_x_vs_y_plot(
94+
oReportSetup,
95+
"Solution Convergence",
96+
"Terminal Solution Data",
97+
setup + " : Adaptivepass",
98+
[],
99+
["Pass:=", ["All"], "Freq:=", ["All"]],
100+
"Pass",
101+
"S [dB]",
102+
unique_output_s,
103+
)
104+
105+
elif oDesign.GetSolutionType() == "Eigenmode":
106+
# Create eigenmode convergence report
107+
solution = setup + " : AdaptivePass"
108+
modes = get_quantities(oReportSetup, "Eigenmode Parameters", solution, [], "Eigen Modes")
109+
create_x_vs_y_plot(
110+
oReportSetup,
111+
"Solution Convergence",
112+
"Eigenmode Parameters",
113+
solution,
114+
[],
115+
["Pass:=", ["All"]],
116+
"Pass",
117+
"Frequency [Hz]",
118+
["re({})".format(m) for m in modes],
119+
)
120+
121+
# Create integral reports
122+
solution = setup + " : LastAdaptive"
123+
integrals = get_quantities(oReportSetup, "Fields", solution, [], "Calculator Expressions")
124+
energies = [e for e in integrals if e.startswith("E_") or e.startswith("Ez_") or e.startswith("Exy_")]
125+
if energies:
126+
create_x_vs_y_plot(
127+
oReportSetup, "Energy Integrals", "Fields", solution, [], ["Phase:=", ["0deg"]], "Phase", "E [J]", energies
128+
)
129+
fluxes = [e for e in integrals if e.startswith("flux_")]
130+
if fluxes:
131+
create_x_vs_y_plot(
132+
oReportSetup,
133+
"Magnetic Fluxes",
134+
"Fields",
135+
solution,
136+
[],
137+
["Phase:=", ["0deg"]],
138+
"Phase",
139+
"Magnetic flux quanta",
140+
fluxes,
141+
)
142+
143+
elif design_type == "Q3D Extractor":
144+
setup = get_enabled_setup(oDesign, tab="General")
145+
nets = oBoundarySetup.GetExcitations()[::2]
146+
net_types = oBoundarySetup.GetExcitations()[1::2]
147+
signal_nets = [net for net, net_type in zip(nets, net_types) if net_type == "SignalNet"]
148+
149+
# Create capacitance vs frequency and capacitance convergence reports
150+
unique_elements_c = [
151+
"C_%s_%s" % (net_i, signal_nets[j]) for i, net_i in enumerate(signal_nets) for j in range(i, len(signal_nets))
152+
] # The unique elements (half matrix), used for plotting
153+
unique_output_c = [e for e in unique_elements_c if e in oOutputVariable.GetOutputVariables()]
154+
if unique_output_c:
155+
create_x_vs_y_plot(
156+
oReportSetup,
157+
"Capacitance vs Frequency",
158+
"Matrix",
159+
setup + " : LastAdaptive",
160+
["Context:=", "Original"],
161+
["Freq:=", ["All"]],
162+
"Freq",
163+
"C",
164+
unique_output_c,
165+
)
166+
create_x_vs_y_plot(
167+
oReportSetup,
168+
"Solution Convergence",
169+
"Matrix",
170+
setup + " : AdaptivePass",
171+
["Context:=", "Original"],
172+
["Pass:=", ["All"], "Freq:=", ["All"]],
173+
"Pass",
174+
"C",
175+
unique_output_c,
176+
)
177+
178+
# Notify the end of script
179+
oDesktop.AddMessage("", "", 0, "Reports created (%s)" % time.asctime(time.localtime()))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# This code is part of KQCircuits
2+
# Copyright (C) 2021 IQM Finland Oy
3+
#
4+
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
5+
# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
6+
# version.
7+
#
8+
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9+
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
#
11+
# You should have received a copy of the GNU General Public License along with this program. If not, see
12+
# https://www.gnu.org/licenses/gpl-3.0.html.
13+
#
14+
# The software distribution should follow IQM trademark policy for open-source software
15+
# (meetiqm.com/developers/osstmpolicy). IQM welcomes contributions to the code. Please see our contribution agreements
16+
# for individuals (meetiqm.com/developers/clas/individual) and organizations (meetiqm.com/developers/clas/organization).
17+
18+
19+
# This is a Python 2.7 script that should be run in HFSS in order to import and run the simulation
20+
import time
21+
import ScriptEnv
22+
23+
## SET UP ENVIRONMENT
24+
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
25+
26+
oDesktop.RestoreWindow()
27+
oProject = oDesktop.GetActiveProject()
28+
oDesign = oProject.GetActiveDesign()
29+
oOutputVariable = oDesign.GetModule("OutputVariable")
30+
31+
outputvars = oOutputVariable.GetOutputVariables()
32+
for x in outputvars:
33+
oOutputVariable.DeleteOutputVariable(x)
34+
35+
oDesktop.AddMessage("", "", 0, "Deleted %d output variables (%s)" % (len(outputvars), time.asctime(time.localtime())))

0 commit comments

Comments
 (0)