setupEM 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- examples/pcb_lowpass/palace_pcb_lowpass.py +120 -0
- examples/sg13_balun_140-170/palace_balun_mesh2.py +120 -0
- examples/sg13_microstrip_fast/palace_demo_line.py +117 -0
- examples/sg13_rfcmim/palace_rfcmim.py +114 -0
- setupEM/__init__.py +9 -0
- setupEM/setupEM.py +2141 -0
- setupem-0.1.1.dist-info/METADATA +57 -0
- setupem-0.1.1.dist-info/RECORD +11 -0
- setupem-0.1.1.dist-info/WHEEL +5 -0
- setupem-0.1.1.dist-info/entry_points.txt +2 -0
- setupem-0.1.1.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# MODEL FOR GMSH WITH PALACE
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
# we expect gds2palace in the same directory as this model file
|
|
8
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'gds2palace')))
|
|
9
|
+
from gds2palace import *
|
|
10
|
+
|
|
11
|
+
# Model comments
|
|
12
|
+
#
|
|
13
|
+
# PCB low pass example, everything is in unit micron (GDS and XML stackup)
|
|
14
|
+
# Port excitation only, so that we get S11 and S21. Reverse path data is padded with zeros.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# ======================== workflow settings ================================
|
|
18
|
+
|
|
19
|
+
#start solver after creating the model?
|
|
20
|
+
start_simulation = False
|
|
21
|
+
run_command = ['./run_sim']
|
|
22
|
+
|
|
23
|
+
# ===================== input files and path settings =======================
|
|
24
|
+
|
|
25
|
+
gds_filename = "pcb_lowpass.gds" # geometries
|
|
26
|
+
XML_filename = "pcb_ro4003.xml" # stackup
|
|
27
|
+
|
|
28
|
+
# preprocess GDSII for safe handling of cutouts/holes?
|
|
29
|
+
preprocess_gds = True
|
|
30
|
+
|
|
31
|
+
# merge via polygons with distance less than .. microns, set to 0 to disable via merging.
|
|
32
|
+
merge_polygon_size = 0
|
|
33
|
+
|
|
34
|
+
# get path for this simulation file
|
|
35
|
+
script_path = utilities.get_script_path(__file__)
|
|
36
|
+
|
|
37
|
+
# use script filename as model basename
|
|
38
|
+
model_basename = utilities.get_basename(__file__)
|
|
39
|
+
|
|
40
|
+
# set and create directory for simulation output
|
|
41
|
+
sim_path = utilities.create_sim_path (script_path,model_basename)
|
|
42
|
+
print('Simulation data directory: ', sim_path)
|
|
43
|
+
|
|
44
|
+
# change path to models script path
|
|
45
|
+
modelDir = os.path.dirname(os.path.abspath(__file__))
|
|
46
|
+
os.chdir(modelDir)
|
|
47
|
+
|
|
48
|
+
# ======================== simulation settings ================================
|
|
49
|
+
|
|
50
|
+
settings = {}
|
|
51
|
+
|
|
52
|
+
settings['unit'] = 1e-6 # geometry is in MILLIMETER for PCB example
|
|
53
|
+
settings['margin'] = 2000 # distance in microns from GDSII geometry boundary to simulation boundary
|
|
54
|
+
settings['air_around'] = [1000,1000,1000,1000,2000, 10000] # airbox size to simulation boundary
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
settings['fstart'] = 0.1e9
|
|
58
|
+
settings['fstop'] = 6.0e9
|
|
59
|
+
settings['fstep'] = 0.05e9
|
|
60
|
+
|
|
61
|
+
settings['refined_cellsize'] = 200 # mesh cell size in conductor region
|
|
62
|
+
settings['cells_per_wavelength'] = 10 # how many mesh cells per wavelength, must be 10 or more
|
|
63
|
+
|
|
64
|
+
settings['meshsize_max'] = 5000 # in project units, override cells_per_wavelength
|
|
65
|
+
settings['adaptive_mesh_iterations'] = 0
|
|
66
|
+
settings['z_thickness_factor'] = 1
|
|
67
|
+
|
|
68
|
+
# settings['nogui'] = True # create files without showing 3D model
|
|
69
|
+
# settings['nogui'] = ('nogui' in sys.argv) # check if nogui specified on command line, then create files without showing 3D model
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# Ports from GDSII Data, polygon geometry from specified special layer
|
|
73
|
+
# Excitations can be switched off by voltage=0, those S-parameter will be incomplete then
|
|
74
|
+
|
|
75
|
+
simulation_ports = simulation_setup.all_simulation_ports()
|
|
76
|
+
# instead of in-plane port specified with target_layername, we here use via port specified with from_layername and to_layername
|
|
77
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=1, voltage=1, port_Z0=50, source_layernum=201, from_layername='Bottom', to_layername='Top', direction='z'))
|
|
78
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=2, voltage=0, port_Z0=50, source_layernum=202, from_layername='Bottom', to_layername='Top', direction='z'))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# ======================== simulation ================================
|
|
82
|
+
|
|
83
|
+
# get technology stackup data
|
|
84
|
+
materials_list, dielectrics_list, metals_list = stackup_reader.read_substrate (XML_filename)
|
|
85
|
+
# get list of layers from technology
|
|
86
|
+
layernumbers = metals_list.getlayernumbers()
|
|
87
|
+
layernumbers.extend(simulation_ports.portlayers)
|
|
88
|
+
|
|
89
|
+
# read geometries from GDSII, only purpose 0
|
|
90
|
+
allpolygons = gds_reader.read_gds(gds_filename, layernumbers, purposelist=[0], metals_list=metals_list, preprocess=preprocess_gds, merge_polygon_size=merge_polygon_size)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
########### create model ###########
|
|
94
|
+
|
|
95
|
+
settings['simulation_ports'] = simulation_ports
|
|
96
|
+
settings['materials_list'] = materials_list
|
|
97
|
+
settings['dielectrics_list'] = dielectrics_list
|
|
98
|
+
settings['metals_list'] = metals_list
|
|
99
|
+
settings['layernumbers'] = layernumbers
|
|
100
|
+
settings['allpolygons'] = allpolygons
|
|
101
|
+
settings['sim_path'] = sim_path
|
|
102
|
+
settings['model_basename'] = model_basename
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# list of ports that are excited (set voltage to zero in port excitation to skip an excitation!)
|
|
106
|
+
excite_ports = simulation_ports.all_active_excitations()
|
|
107
|
+
config_name, data_dir = simulation_setup.create_palace (excite_ports, settings)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# for convenience, write run script to model directory
|
|
111
|
+
utilities.create_run_script(sim_path)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
if start_simulation:
|
|
115
|
+
try:
|
|
116
|
+
os.chdir(sim_path)
|
|
117
|
+
subprocess.run(run_command, shell=True)
|
|
118
|
+
except:
|
|
119
|
+
print(f"Unable to run Palace using command ",run_command)
|
|
120
|
+
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# MODEL FOR GMSH WITH PALACE
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
# we expect gds2palace in the same directory as this model file
|
|
8
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'gds2palace')))
|
|
9
|
+
from gds2palace import *
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# Model comments
|
|
13
|
+
#
|
|
14
|
+
# Balun from D-Band phase shifter design by Rupok Das, Neural Semi, in Tapeout July 2025
|
|
15
|
+
# Design frequency 140-170 GHz
|
|
16
|
+
# https://github.com/IHP-GmbH/TO_July2025/tree/main/FMD_QNC_D_Band_Phase_Shifter
|
|
17
|
+
# Ports: Model uses a via port that is defined between Metal3 and TopMetal2
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# ======================== workflow settings ================================
|
|
21
|
+
|
|
22
|
+
# preview model/mesh only, without running solver?
|
|
23
|
+
start_simulation = False
|
|
24
|
+
run_command = ['start', 'wsl.exe']
|
|
25
|
+
|
|
26
|
+
# ===================== input files and path settings =======================
|
|
27
|
+
|
|
28
|
+
gds_filename = "Balun_140-170G_RupokDas_with_ports.gds" # geometries
|
|
29
|
+
XML_filename = "SG13G2_nosub.xml" # stackup
|
|
30
|
+
|
|
31
|
+
# preprocess GDSII for safe handling of cutouts/holes?
|
|
32
|
+
preprocess_gds = False
|
|
33
|
+
|
|
34
|
+
# merge via polygons with distance less than .. microns, set to 0 to disable via merging.
|
|
35
|
+
merge_polygon_size = 2.0
|
|
36
|
+
|
|
37
|
+
# get path for this simulation file
|
|
38
|
+
script_path = utilities.get_script_path(__file__)
|
|
39
|
+
|
|
40
|
+
# use script filename as model basename
|
|
41
|
+
model_basename = utilities.get_basename(__file__)
|
|
42
|
+
|
|
43
|
+
# set and create directory for simulation output
|
|
44
|
+
sim_path = utilities.create_sim_path (script_path,model_basename)
|
|
45
|
+
print('Simulation data directory: ', sim_path)
|
|
46
|
+
|
|
47
|
+
# change path to models script path
|
|
48
|
+
modelDir = os.path.dirname(os.path.abspath(__file__))
|
|
49
|
+
os.chdir(modelDir)
|
|
50
|
+
|
|
51
|
+
# ======================== simulation settings ================================
|
|
52
|
+
|
|
53
|
+
settings = {}
|
|
54
|
+
|
|
55
|
+
settings['unit'] = 1e-6 # geometry is in microns
|
|
56
|
+
settings['margin'] = 50 # distance in microns from GDSII geometry boundary to simulation boundary
|
|
57
|
+
|
|
58
|
+
settings['fstart'] = 100e9
|
|
59
|
+
settings['fstop'] = 200e9
|
|
60
|
+
settings['fstep'] = 1e9
|
|
61
|
+
|
|
62
|
+
settings['refined_cellsize'] = 2 # mesh cell size in conductor region
|
|
63
|
+
settings['cells_per_wavelength'] = 10 # how many mesh cells per wavelength, must be 10 or more
|
|
64
|
+
|
|
65
|
+
settings['meshsize_max'] = 70 # microns, override cells_per_wavelength
|
|
66
|
+
settings['adaptive_mesh_iterations'] = 0
|
|
67
|
+
settings['z_thickness_factor'] = 0.33
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ports from GDSII Data, polygon geometry from specified special layer
|
|
71
|
+
# note that for multiport simulation, excitations are switched on/off in simulation_setup.createSimulation below
|
|
72
|
+
|
|
73
|
+
simulation_ports = simulation_setup.all_simulation_ports()
|
|
74
|
+
# instead of in-plane port specified with target_layername, we here use via port specified with from_layername and to_layername
|
|
75
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=1, voltage=1, port_Z0=50, source_layernum=201, from_layername='Metal3', to_layername='TopMetal2', direction='z'))
|
|
76
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=2, voltage=1, port_Z0=50, source_layernum=202, from_layername='Metal3', to_layername='TopMetal2', direction='z'))
|
|
77
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=3, voltage=1, port_Z0=50, source_layernum=203, from_layername='Metal3', to_layername='TopMetal2', direction='z'))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# ======================== simulation ================================
|
|
81
|
+
|
|
82
|
+
# get technology stackup data
|
|
83
|
+
materials_list, dielectrics_list, metals_list = stackup_reader.read_substrate (XML_filename)
|
|
84
|
+
# get list of layers from technology
|
|
85
|
+
layernumbers = metals_list.getlayernumbers()
|
|
86
|
+
layernumbers.extend(simulation_ports.portlayers)
|
|
87
|
+
|
|
88
|
+
# read geometries from GDSII, only purpose 0
|
|
89
|
+
allpolygons = gds_reader.read_gds(gds_filename, layernumbers, purposelist=[0], metals_list=metals_list, preprocess=preprocess_gds, merge_polygon_size=merge_polygon_size)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
########### create model ###########
|
|
93
|
+
|
|
94
|
+
settings['simulation_ports'] = simulation_ports
|
|
95
|
+
settings['materials_list'] = materials_list
|
|
96
|
+
settings['dielectrics_list'] = dielectrics_list
|
|
97
|
+
settings['metals_list'] = metals_list
|
|
98
|
+
settings['layernumbers'] = layernumbers
|
|
99
|
+
settings['allpolygons'] = allpolygons
|
|
100
|
+
settings['sim_path'] = sim_path
|
|
101
|
+
settings['model_basename'] = model_basename
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# list of ports that are excited (set voltage to zero in port excitation to skip an excitation!)
|
|
105
|
+
excite_ports = simulation_ports.all_active_excitations()
|
|
106
|
+
config_name, data_dir = simulation_setup.create_palace (excite_ports, settings)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# for convenience, write run script to model directory
|
|
110
|
+
utilities.create_run_script(sim_path)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
if start_simulation:
|
|
114
|
+
try:
|
|
115
|
+
os.chdir(sim_path)
|
|
116
|
+
subprocess.run(run_command, shell=True)
|
|
117
|
+
except:
|
|
118
|
+
print(f"Unable to run Palace using command ",run_command)
|
|
119
|
+
|
|
120
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# MODEL FOR GMSH WITH PALACE
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
# we expect gds2palace in the same directory as this model file
|
|
8
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'gds2palace')))
|
|
9
|
+
from gds2palace import *
|
|
10
|
+
|
|
11
|
+
# Model comments
|
|
12
|
+
#
|
|
13
|
+
# Ports: Model uses a via port that is defined between Metal1 and TopMetal2 (not using in-plane port here)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# ======================== workflow settings ================================
|
|
17
|
+
|
|
18
|
+
#start solver after creating the model?
|
|
19
|
+
start_simulation = False
|
|
20
|
+
run_command = ['./run_sim']
|
|
21
|
+
|
|
22
|
+
# ===================== input files and path settings =======================
|
|
23
|
+
|
|
24
|
+
gds_filename = "line_short_viaport.gds" # geometries
|
|
25
|
+
XML_filename = "SG13G2_nosub.xml" # stackup
|
|
26
|
+
|
|
27
|
+
# preprocess GDSII for safe handling of cutouts/holes?
|
|
28
|
+
preprocess_gds = False
|
|
29
|
+
|
|
30
|
+
# merge via polygons with distance less than .. microns, set to 0 to disable via merging.
|
|
31
|
+
merge_polygon_size = 0
|
|
32
|
+
|
|
33
|
+
# get path for this simulation file
|
|
34
|
+
script_path = utilities.get_script_path(__file__)
|
|
35
|
+
|
|
36
|
+
# use script filename as model basename
|
|
37
|
+
model_basename = utilities.get_basename(__file__)
|
|
38
|
+
|
|
39
|
+
# set and create directory for simulation output
|
|
40
|
+
sim_path = utilities.create_sim_path (script_path,model_basename)
|
|
41
|
+
print('Simulation data directory: ', sim_path)
|
|
42
|
+
|
|
43
|
+
# change path to models script path
|
|
44
|
+
modelDir = os.path.dirname(os.path.abspath(__file__))
|
|
45
|
+
os.chdir(modelDir)
|
|
46
|
+
|
|
47
|
+
# ======================== simulation settings ================================
|
|
48
|
+
|
|
49
|
+
settings = {}
|
|
50
|
+
|
|
51
|
+
settings['unit'] = 1e-6 # geometry is in microns
|
|
52
|
+
settings['margin'] = 50 # distance in microns from GDSII geometry boundary to simulation boundary
|
|
53
|
+
|
|
54
|
+
settings['fstart'] = 0e9
|
|
55
|
+
settings['fstop'] = 50e9
|
|
56
|
+
settings['fstep'] = 2.5e9
|
|
57
|
+
|
|
58
|
+
settings['refined_cellsize'] = 5 # mesh cell size in conductor region
|
|
59
|
+
settings['cells_per_wavelength'] = 10 # how many mesh cells per wavelength, must be 10 or more
|
|
60
|
+
|
|
61
|
+
settings['meshsize_max'] = 70 # microns, override cells_per_wavelength
|
|
62
|
+
settings['adaptive_mesh_iterations'] = 0
|
|
63
|
+
settings['z_thickness_factor'] = 0.33
|
|
64
|
+
|
|
65
|
+
# settings['nogui'] = True # create files without showing 3D model
|
|
66
|
+
# settings['nogui'] = ('nogui' in sys.argv) # check if nogui specified on command line, then create files without showing 3D model
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Ports from GDSII Data, polygon geometry from specified special layer
|
|
70
|
+
# Excitations can be switched off by voltage=0, those S-parameter will be incomplete then
|
|
71
|
+
|
|
72
|
+
simulation_ports = simulation_setup.all_simulation_ports()
|
|
73
|
+
# instead of in-plane port specified with target_layername, we here use via port specified with from_layername and to_layername
|
|
74
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=1, voltage=1, port_Z0=50, source_layernum=201, from_layername='Metal1', to_layername='TopMetal2', direction='z'))
|
|
75
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=2, voltage=0, port_Z0=50, source_layernum=202, from_layername='Metal1', to_layername='TopMetal2', direction='z'))
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# ======================== simulation ================================
|
|
79
|
+
|
|
80
|
+
# get technology stackup data
|
|
81
|
+
materials_list, dielectrics_list, metals_list = stackup_reader.read_substrate (XML_filename)
|
|
82
|
+
# get list of layers from technology
|
|
83
|
+
layernumbers = metals_list.getlayernumbers()
|
|
84
|
+
layernumbers.extend(simulation_ports.portlayers)
|
|
85
|
+
|
|
86
|
+
# read geometries from GDSII, only purpose 0
|
|
87
|
+
allpolygons = gds_reader.read_gds(gds_filename, layernumbers, purposelist=[0], metals_list=metals_list, preprocess=preprocess_gds, merge_polygon_size=merge_polygon_size)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
########### create model ###########
|
|
91
|
+
|
|
92
|
+
settings['simulation_ports'] = simulation_ports
|
|
93
|
+
settings['materials_list'] = materials_list
|
|
94
|
+
settings['dielectrics_list'] = dielectrics_list
|
|
95
|
+
settings['metals_list'] = metals_list
|
|
96
|
+
settings['layernumbers'] = layernumbers
|
|
97
|
+
settings['allpolygons'] = allpolygons
|
|
98
|
+
settings['sim_path'] = sim_path
|
|
99
|
+
settings['model_basename'] = model_basename
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# list of ports that are excited (set voltage to zero in port excitation to skip an excitation!)
|
|
103
|
+
excite_ports = simulation_ports.all_active_excitations()
|
|
104
|
+
config_name, data_dir = simulation_setup.create_palace (excite_ports, settings)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# for convenience, write run script to model directory
|
|
108
|
+
utilities.create_run_script(sim_path)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
if start_simulation:
|
|
112
|
+
try:
|
|
113
|
+
os.chdir(sim_path)
|
|
114
|
+
subprocess.run(run_command, shell=True)
|
|
115
|
+
except:
|
|
116
|
+
print(f"Unable to run Palace using command ",run_command)
|
|
117
|
+
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# MODEL FOR GMSH WITH PALACE
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import subprocess
|
|
6
|
+
|
|
7
|
+
# we expect gds2palace in the same directory as this model file
|
|
8
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'gds2palace')))
|
|
9
|
+
from gds2palace import *
|
|
10
|
+
|
|
11
|
+
# Model comments
|
|
12
|
+
#
|
|
13
|
+
# Ports: Model uses a via port that is defined between Metal1 and TopMetal2 (not using in-plane port here)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# ======================== workflow settings ================================
|
|
17
|
+
|
|
18
|
+
#start solver after creating the model?
|
|
19
|
+
start_simulation = False
|
|
20
|
+
run_command = ['./run_sim']
|
|
21
|
+
|
|
22
|
+
# ===================== input files and path settings =======================
|
|
23
|
+
|
|
24
|
+
gds_filename = "rfcmim_30x15x10_full.gds" # geometries
|
|
25
|
+
XML_filename = "SG13G2_200um.xml" # stackup
|
|
26
|
+
|
|
27
|
+
# preprocess GDSII for safe handling of cutouts/holes?
|
|
28
|
+
preprocess_gds = True
|
|
29
|
+
|
|
30
|
+
# merge via polygons with distance less than .. microns, set to 0 to disable via merging.
|
|
31
|
+
merge_polygon_size = 2
|
|
32
|
+
|
|
33
|
+
# get path for this simulation file
|
|
34
|
+
script_path = utilities.get_script_path(__file__)
|
|
35
|
+
|
|
36
|
+
# use script filename as model basename
|
|
37
|
+
model_basename = utilities.get_basename(__file__)
|
|
38
|
+
|
|
39
|
+
# set and create directory for simulation output
|
|
40
|
+
sim_path = utilities.create_sim_path (script_path,model_basename)
|
|
41
|
+
print('Simulation data directory: ', sim_path)
|
|
42
|
+
|
|
43
|
+
# change path to models script path
|
|
44
|
+
modelDir = os.path.dirname(os.path.abspath(__file__))
|
|
45
|
+
os.chdir(modelDir)
|
|
46
|
+
|
|
47
|
+
# ======================== simulation settings ================================
|
|
48
|
+
|
|
49
|
+
settings = {}
|
|
50
|
+
|
|
51
|
+
settings['unit'] = 1e-6 # geometry is in microns
|
|
52
|
+
settings['margin'] = 50 # distance in microns from GDSII geometry boundary to simulation boundary
|
|
53
|
+
|
|
54
|
+
settings['fstart'] = 0e9
|
|
55
|
+
settings['fstop'] = 100e9
|
|
56
|
+
settings['fstep'] = 1e9
|
|
57
|
+
|
|
58
|
+
settings['refined_cellsize'] = 2 # mesh cell size in conductor region
|
|
59
|
+
settings['cells_per_wavelength'] = 10 # how many mesh cells per wavelength, must be 10 or more
|
|
60
|
+
|
|
61
|
+
settings['meshsize_max'] = 70 # microns, override cells_per_wavelength
|
|
62
|
+
settings['adaptive_mesh_iterations'] = 0
|
|
63
|
+
settings['z_thickness_factor'] = 0.33
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Ports from GDSII Data, polygon geometry from specified special layer
|
|
67
|
+
# Excitations can be switched off by voltage=0, those S-parameter will be incomplete then
|
|
68
|
+
|
|
69
|
+
simulation_ports = simulation_setup.all_simulation_ports()
|
|
70
|
+
# instead of in-plane port specified with target_layername, we here use via port specified with from_layername and to_layername
|
|
71
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=1, voltage=1, port_Z0=50, source_layernum=201, from_layername='Metal1', to_layername='TopMetal1', direction='z'))
|
|
72
|
+
simulation_ports.add_port(simulation_setup.simulation_port(portnumber=2, voltage=1, port_Z0=50, source_layernum=202, from_layername='Metal1', to_layername='Metal5', direction='z'))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# ======================== simulation ================================
|
|
76
|
+
|
|
77
|
+
# get technology stackup data
|
|
78
|
+
materials_list, dielectrics_list, metals_list = stackup_reader.read_substrate (XML_filename)
|
|
79
|
+
# get list of layers from technology
|
|
80
|
+
layernumbers = metals_list.getlayernumbers()
|
|
81
|
+
layernumbers.extend(simulation_ports.portlayers)
|
|
82
|
+
|
|
83
|
+
# read geometries from GDSII, only purpose 0
|
|
84
|
+
allpolygons = gds_reader.read_gds(gds_filename, layernumbers, purposelist=[0], metals_list=metals_list, preprocess=preprocess_gds, merge_polygon_size=merge_polygon_size)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
########### create model ###########
|
|
88
|
+
|
|
89
|
+
settings['simulation_ports'] = simulation_ports
|
|
90
|
+
settings['materials_list'] = materials_list
|
|
91
|
+
settings['dielectrics_list'] = dielectrics_list
|
|
92
|
+
settings['metals_list'] = metals_list
|
|
93
|
+
settings['layernumbers'] = layernumbers
|
|
94
|
+
settings['allpolygons'] = allpolygons
|
|
95
|
+
settings['sim_path'] = sim_path
|
|
96
|
+
settings['model_basename'] = model_basename
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# list of ports that are excited (set voltage to zero in port excitation to skip an excitation!)
|
|
100
|
+
excite_ports = simulation_ports.all_active_excitations()
|
|
101
|
+
config_name, data_dir = simulation_setup.create_palace (excite_ports, settings)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# for convenience, write run script to model directory
|
|
105
|
+
utilities.create_run_script(sim_path)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if start_simulation:
|
|
109
|
+
try:
|
|
110
|
+
os.chdir(sim_path)
|
|
111
|
+
subprocess.run(run_command, shell=True)
|
|
112
|
+
except:
|
|
113
|
+
print(f"Unable to run Palace using command ",run_command)
|
|
114
|
+
|