def z0_for_width(width: float) -> float: """ """ sim = Simulation(freq=freq, unit=1e-3, reference_frequency=ref_freq, sim_dir=None) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=width, propagation_axis=Axis("x"), port_number=1, excite=True, ref_impedance=50, ) Mesh( sim=sim, metal_res=1 / 80, nonmetal_res=1 / 10, min_lines=5, expand_bounds=((0, 0), (0, 0), (10, 40)), ) sim.run(csx=False) return np.abs(sim.ports[0].impedance(freq=ref_freq))
def func(min_lines: int): sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq, sim_dir=None) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=trace_width, propagation_axis=Axis("x"), port_number=1, excite=True, ) Mesh( sim=sim, metal_res=1 / 80, nonmetal_res=1 / 10, smooth=(1.1, 1.5, 1.5), min_lines=min_lines, expand_bounds=((0, 0), (0, 0), (10, 40)), ) sim.run(csx=False) return sim.ports[0].impedance()
def func(gnd_gap: float): sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq, sim_dir=None) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=trace_width, propagation_axis=Axis("x"), gnd_gap=(gnd_gap, gnd_gap), port_number=1, excite=True, ref_impedance=50, ) Mesh( sim=sim, metal_res=1 / 80, nonmetal_res=1 / 10, min_lines=9, expand_bounds=((0, 0), (0, 0), (10, 40)), ) sim.run(csx=False) return np.abs(sim.ports[0].impedance(freq=ref_freq))
def sim_impedance(sim: Simulation): """ Get the characteristic impedance of a simulation. """ sim.run(csx=False) ports = sim.ports z0 = ports[0].impedance() idx = array_index(sim.center_frequency(), sim.freq) return np.abs(z0[idx])
def gcpw(trace_width: float): """ """ sim = Simulation(freq=freq, unit=1e-3) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), ) box = Box2( Coordinate2(-pcb_len / 2, -trace_width / 2), Coordinate2(pcb_len / 2, trace_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=box.width(), propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, gnd_gap=(gap, gap), port_number=1, ref_impedance=50, excite=True, ) ViaWall( pcb=pcb, position=Coordinate2(0, trace_width / 2 + gap + via_gap), length=pcb_len, width=via_gap / 2, ) ViaWall( pcb=pcb, position=Coordinate2(0, -trace_width / 2 - gap - via_gap), length=pcb_len, width=via_gap / 2, ) Mesh( sim=sim, metal_res=1 / 120, nonmetal_res=1 / 40, smooth=(1.1, 1.5, 1.5), min_lines=25, expand_bounds=((0, 0), (24, 24), (24, 24)), ) sim.run(csx=False) return np.average(np.abs(np.abs(sim.ports[0].impedance()) - 50))
def func(width: float): sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq, sim_dir=None) pcb_prop = common_pcbs["oshpark4"] pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) DifferentialMicrostrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=width, gap=trace_gap, propagation_axis=Axis("x"), port_number=1, excite=True, ref_impedance=50, ) Mesh( sim=sim, metal_res=1 / 80, nonmetal_res=1 / 10, min_lines=9, expand_bounds=((0, 0), (0, 0), (10, 40)), ) FieldDump( sim=sim, box=Box3( Coordinate3(-pcb_len / 2, -pcb_width / 2, 0), Coordinate3(pcb_len / 2, pcb_width / 2, 0), ), dump_type=DumpType.current_density_time, ) sim.run(csx=False) return np.abs(sim.ports[0].impedance(freq=ref_freq))
def gen_sim(width: float) -> Simulation: """ Create simulation objects to sweep over. :param width: Top layer trace width. This is the parameter we sweep over. """ sim = Simulation(freq=freq, unit=1e-3) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), ) box = Box2( Coordinate2(-pcb_len / 2, -width / 2), Coordinate2(pcb_len / 2, width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=box.width(), propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, gnd_gap=(gap, gap), port_number=1, feed_shift=0.3, ref_impedance=50, excite=True, ) Mesh( sim=sim, metal_res=1 / 80, nonmetal_res=1 / 40, smooth=(1.2, 1.5, 1.5), min_lines=25, expand_bounds=((0, 0), (8, 8), (8, 20)), ) return sim_impedance(sim)
from pyems.mesh import Mesh from pyems.field_dump import FieldDump, DumpType from pyems.utilities import print_table, mil_to_mm from pyems.csxcad import ( add_metal, add_material, add_conducting_sheet, colors, construct_box, construct_cylinder, ) freq = np.arange(0, 18e9, 1e7) ref_freq = 5.6e9 unit = 1e-3 sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq) coax_len = 10 trace_width = 0.38 coax_dielectric = common_dielectrics["PTFE"] coax_rad = mil_to_mm(190 / 2) # RG-141 core_rad = (coax_core_diameter( 2 * coax_rad, coax_dielectric.epsr_at_freq(sim.reference_frequency)) / 2) sma_lead_len = 1.9 sma_lead_width = 0.51 sma_lead_height = 0.25 # sma_keepout_width = sma_lead_width + 2 * gap sma_rect_width = 9.53 sma_rect_height = 7.92
def func(params: List[float]): """ """ cutout_width = params[0] sim = Simulation(freq=freq, unit=unit, sim_dir=None) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) box = Box2( Coordinate2(-pcb_len / 2, -trace_width / 2), Coordinate2(-(cap_dim.length / 2) - (pad_length / 2), trace_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=box.width(), propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, port_number=1, excite=True, feed_shift=0.35, ref_impedance=z0_ref, ) SMDPassive( pcb=pcb, position=Coordinate2(0, 0), axis=Axis("x"), dimensions=cap_dim, pad_width=pad_width, pad_length=pad_length, c=10e-12, pcb_layer=0, gnd_cutout_width=cutout_width, gnd_cutout_length=1, ) box = Box2( Coordinate2(pcb_len / 2, trace_width / 2), Coordinate2((cap_dim.length / 2) + (pad_length / 2), -trace_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=box.width(), propagation_axis=Axis("x", direction=-1), trace_layer=0, gnd_layer=1, port_number=2, excite=False, ref_impedance=z0_ref, ) Mesh( sim=sim, metal_res=1 / 120, nonmetal_res=1 / 40, smooth=(1.2, 1.2, 1.2), min_lines=5, expand_bounds=((0, 0), (0, 0), (10, 20)), ) sim.run(csx=False) print_table( data=[sim.freq / 1e9, sim.s_param(1, 1), sim.s_param(2, 1)], col_names=["freq", "s11", "s21"], prec=[4, 4, 4], ) return np.sum(sim.s_param(1, 1))
from pyems.pcb import common_pcbs from pyems.structure import ( DifferentialMicrostrip, PCB, common_smd_passives, SMDPassive, ) from pyems.coordinate import Coordinate2, Axis, Box3, Coordinate3 from pyems.utilities import print_table, mil_to_mm from pyems.field_dump import FieldDump, DumpType from pyems.mesh import Mesh freq = np.arange(4e9, 18e9, 10e6) unit = 1e-3 ref_freq = 5.6e9 sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq) pcb_len = 30 pcb_width = 10 trace_width = 0.85 gnd_gap = mil_to_mm(6) trace_gap = mil_to_mm(6) via_gap = 0.4 cap_dim = common_smd_passives["0402C"] cap_dim.set_unit(unit) pad_length = 0.6 pad_width = trace_width pcb_prop = common_pcbs["oshpark4"]
from pyems.simulation import Simulation from pyems.mesh import Mesh from pyems.pcb import common_pcbs from pyems.coordinate import Coordinate2, Axis from pyems.utilities import print_table freq = np.arange(1e9, 18e9, 1e7) ref_freq = 5.6e9 unit = 1e-3 pcb_len = 10 pcb_width = 10 trace_width = 0.38 pcb_prop = common_pcbs["oshpark4"] gnd_gap = 0.900 * trace_width sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=trace_width, propagation_axis=Axis("x"), gnd_gap=(gnd_gap, gnd_gap),
import os import sys import numpy as np from pyems.utilities import print_table from pyems.port import RectWaveguidePort from pyems.simulation import Simulation from pyems.field_dump import FieldDump from pyems.structure import standard_waveguides from pyems.coordinate import Coordinate3, Box3, Axis from pyems.mesh import Mesh from pyems.nf2ff import NF2FF unit = 1e-3 freq = np.linspace(5.3e9, 5.9e9, 501) sim = Simulation(freq=freq, unit=unit) metal = sim.csx.AddMetal("metal") stl = metal.AddPolyhedronReader(filename=os.path.abspath("horn-antenna.stl")) stl.ReadFile() wg = standard_waveguides["WR159"] wg.set_unit(unit) wg_len = 40 port = RectWaveguidePort( sim=sim, box=Box3( Coordinate3(-wg.a / 2, -wg.b / 2, -wg_len), Coordinate3(wg.a / 2, wg.b / 2, 0), ), propagation_axis=Axis("z"),
freq = np.linspace(4e9, 8e9, 501) pcb_len = 40 pcb_width = 10 gcpw_width = 0.34 gcpw_gap = mil_to_mm(6) via_gap = 0.4 # drill_radius = gcpw_width / 2 - pcb_prop.via_plating_thickness(unit) drill_radius = 0.13 drill_diam = 2 * drill_radius annular_width = 0.145 antipad = gcpw_gap keepout_radius = drill_radius + annular_width + antipad via_sep = 0.76 via_fence_sep = via_sep * 2 sim = Simulation(freq=freq, unit=unit) pcb = PCB(sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width) box = Box2( Coordinate2(-pcb_len / 2, -gcpw_width / 2), Coordinate2(pcb_len / 4, gcpw_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=box.width(), propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, gnd_gap=(gcpw_gap, gcpw_gap), via_gap=(via_gap, via_gap),
def sim_func(cutout_width: float): """ """ sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq) core_rad = (coax_core_diameter( 2 * coax_rad, coax_dielectric.epsr_at_freq(sim.reference_frequency)) / 2) pcb_prop = common_pcbs["oshpark4"] pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=pcb_len, width=trace_width, propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, port_number=1, ref_impedance=50, excite=True, ) # Mueller BU-1420701851 edge mount SMA pad = sim.csx.AddConductingSheet( "pad", conductivity=pcb_prop.metal_conductivity(), thickness=pcb_prop.copper_thickness(0), ) pad.AddBox( priority=priorities["trace"], start=[pcb_len / 2 - sma_lead_len / 2, -sma_lead_width / 2, 0], stop=[pcb_len / 2, sma_lead_width / 2, 0], ) pad_cutout = sim.csx.AddMaterial( "gnd_cutout", epsilon=pcb_prop.substrate.epsr_at_freq(ref_freq), kappa=pcb_prop.substrate.kappa_at_freq(ref_freq), ) pad_cutout.AddBox( priority=priorities["keepout"], start=[ pcb_len / 2 - sma_lead_len / 2, -cutout_width / 2, pcb.copper_layer_elevation(1), ], stop=[pcb_len / 2, cutout_width / 2, pcb.copper_layer_elevation(1)], ) sma_box = sim.csx.AddMetal("sma_box") sma_box.AddBox( priority=priorities["ground"], start=[ pcb_len / 2, -sma_rect_width / 2, -sma_rect_height / 2 + sma_lead_height / 2, ], stop=[ pcb_len / 2 + sma_rect_length, sma_rect_width / 2, sma_rect_height / 2 + sma_lead_height / 2, ], ) sma_keepout = sim.csx.AddMaterial( "sma_keepout", epsilon=coax_dielectric.epsr_at_freq(ref_freq), kappa=coax_dielectric.kappa_at_freq(ref_freq), ) sma_keepout.AddCylinder( priority=priorities["keepout"], start=[pcb_len / 2, 0, sma_lead_height / 2], stop=[pcb_len / 2 + sma_rect_length, 0, sma_lead_height / 2], radius=coax_rad, ) for ypos in [ -sma_rect_width / 2, sma_rect_width / 2 - sma_gnd_prong_width, ]: # sma_box.AddBox( # priority=priorities["ground"], # start=[pcb_len / 2 - sma_gnd_prong_len, ypos, 0], # stop=[ # pcb_len / 2, # ypos + sma_gnd_prong_width, # sma_gnd_prong_height # ], # ) # sma_box.AddBox( # priority=priorities["ground"], # start=[ # pcb_len / 2 - sma_gnd_prong_len, # ypos, # pcb.copper_layer_elevation(1) # ], # stop=[ # pcb_len / 2, # ypos + sma_gnd_prong_width, # pcb.copper_layer_elevation(1) - sma_gnd_prong_height, # ], # ) sma_box.AddBox( priority=priorities["ground"], start=[ pcb_len / 2 - sma_gnd_prong_len, ypos, pcb.copper_layer_elevation(1) - sma_gnd_prong_height, ], stop=[ pcb_len / 2, ypos + sma_gnd_prong_width, sma_gnd_prong_height, ], ) lead = sim.csx.AddMetal("lead") lead.AddBox( priority=priorities["trace"], start=[pcb_len / 2 - sma_lead_len / 2, -sma_lead_width / 2, 0], stop=[ pcb_len / 2 + sma_rect_length, sma_lead_width / 2, sma_lead_height, ], ) # coax port Coax( sim=sim, position=Coordinate3( pcb_len / 2 + sma_rect_length + coax_len / 2, 0, sma_lead_height / 2, ), length=coax_len, radius=coax_rad, core_radius=core_rad, shield_thickness=mil_to_mm(5), dielectric=coax_dielectric, propagation_axis=Axis("x", direction=-1), port_number=2, ref_impedance=50, ) mesh = Mesh( sim=sim, metal_res=1 / 120, nonmetal_res=1 / 10, min_lines=5, expand_bounds=((0, 0), (0, 0), (10, 10)), ) box = mesh.sim_box(include_pml=False) sim.run(csx=False) s11 = sim.s_param(1, 1) s21 = sim.s_param(2, 1) print("cutout width: {}".format(cutout_width)) print_table( data=[sim.freq / 1e9, s11, s21], col_names=["freq", "s11", "s21"], prec=[4, 4, 4], ) return np.sum(s11)
def sim_func(taper_angle: float): """ :param taper_angle: Linear taper angle in degrees. """ angle_rad = taper_angle * np.pi / 180 dy = np.abs(trace_width - microstrip_discontinuity_width) / 2 dx = dy / np.tan(angle_rad) taper_middle = microstrip_discontinuity_length / 2 + dx / 2 taper_end = microstrip_discontinuity_length / 2 + dx sim = Simulation(freq=freq, unit=unit, sim_dir=None) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=microstrip_discontinuity_length, width=microstrip_discontinuity_width, propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, ) Taper( pcb=pcb, position=Coordinate2(-taper_middle, 0), pcb_layer=0, width1=trace_width, width2=microstrip_discontinuity_width, length=dx, ) Taper( pcb=pcb, position=Coordinate2(taper_middle, 0), pcb_layer=0, width1=microstrip_discontinuity_width, width2=trace_width, length=dx, ) box = Box2( Coordinate2(-pcb_len / 2, -trace_width / 2), Coordinate2(-taper_end, trace_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=trace_width, propagation_axis=Axis("x"), trace_layer=0, gnd_layer=1, port_number=1, excite=True, feed_shift=0.35, ref_impedance=50, ) box = Box2( Coordinate2(taper_end, -trace_width / 2), Coordinate2(pcb_len / 2, trace_width / 2), ) Microstrip( pcb=pcb, position=box.center(), length=box.length(), width=trace_width, propagation_axis=Axis("x", direction=-1), trace_layer=0, gnd_layer=1, port_number=2, ref_impedance=50, ) Mesh( sim=sim, metal_res=1 / 120, nonmetal_res=1 / 40, min_lines=5, expand_bounds=((0, 0), (0, 0), (10, 40)), ) # sim.run(csx=False) sim.run() return sim.s_param(1, 1)
#!/usr/bin/env python3 import os import sys import numpy as np from pyems.simulation import Simulation from pyems.structure import PCB, Microstrip, ViaWall from pyems.coordinate import Coordinate2, Coordinate3, Box2, Box3, Axis from pyems.pcb import common_pcbs from pyems.mesh import Mesh from pyems.utilities import print_table, mil_to_mm from pyems.field_dump import FieldDump freq = np.arange(0, 18e9, 1e7) sim = Simulation(freq=freq, unit=1e-3) pcb_prop = common_pcbs["oshpark4"] pcb_len = 20 pcb_width = 5 trace_width = 0.34 gap = mil_to_mm(6) via_gap = 0.4 pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), ) box = Box2( Coordinate2(-pcb_len / 2, -trace_width / 2),
min_wavelength=wavelength(center_freq + delta_freq, unit), # metal_res=1 / 40, min_lines=2, expand_bounds=[20, 20, 20, 20, 10, 40], ) network._write_csx() network.view() sim_box = network.get_sim_box() field_dump = FieldDump(csx=csx, box=sim_box) sim = Simulation( fdtd=fdtd, csx=csx, center_freq=center_freq, half_bandwidth=delta_freq, boundary_conditions=["PML_8", "PML_8", "PML_8", "PML_8", "PML_8", "PML_8"], network=network, field_dumps=[field_dump], ) sim.simulate(nf2ff=True) sim.view_field() s11 = network.s_param(1, 1) ports = network.get_ports() freq = sim.get_freq() with open(os.path.abspath("../.data/s11.dat"), "w+") as fout: pretty_print( np.concatenate(([freq / 1e9], [s11])),
from pyems.field_dump import FieldDump, DumpType unit = 1e-3 ref_freq = 5.6e9 freq_res = 1e7 freq = np.arange(0, 18e9 + freq_res, freq_res) pcb_prop = common_pcbs["oshpark4"] pcb_len = 10 pcb_width = 5 trace_width = 0.38 z0_ref = 50 microstrip_discontinuity_width = 0.5 microstrip_discontinuity_length = 1 sim = Simulation(freq=freq, unit=unit, reference_frequency=5.6e9) pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb, position=Coordinate2(0, 0), length=microstrip_discontinuity_length, width=microstrip_discontinuity_width, propagation_axis=Axis("x"),
def sim(): from pyems.simulation import Simulation return Simulation(freq=np.linspace(4e9, 8e9, 501), unit=1e-3)
#!/usr/bin/env python import numpy as np from pyems.structure import PCB, Microstrip from pyems.simulation import Simulation from pyems.mesh import Mesh from pyems.pcb import common_pcbs from pyems.coordinate import Coordinate2, Axis, Box3, Coordinate3 from pyems.field_dump import FieldDump, DumpType from pyems.utilities import print_table freq = np.arange(0, 18e9, 1e7) ref_freq = 5.6e9 unit = 1e-3 sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq) pcb_len = 10 pcb_width = 5 trace_width = 0.38 pcb_prop = common_pcbs["oshpark4"] pcb = PCB( sim=sim, pcb_prop=pcb_prop, length=pcb_len, width=pcb_width, layers=range(3), omit_copper=[0], ) Microstrip( pcb=pcb,
import numpy as np from pyems.simulation import Simulation from pyems.structure import Coax from pyems.coordinate import Coordinate3, Axis from pyems.utilities import mil_to_mm, print_table from pyems.calc import coax_core_diameter from pyems.material import common_dielectrics from pyems.field_dump import FieldDump, DumpType from pyems.mesh import Mesh from pyems.boundary import BoundaryConditions freq = np.arange(4e9, 18e9, 1e7) unit = 1e-3 sim = Simulation( freq=freq, unit=unit, boundary_conditions=BoundaryConditions( (("PML_8", "PML_8"), ("PML_8", "PML_8"), ("PML_8", "PML_8")), ), ) dielectric = common_dielectrics["PTFE"] length = 50 coax_rad = mil_to_mm(190 / 2) # RG-141 core_rad = (coax_core_diameter( 2 * coax_rad, dielectric.epsr_at_freq(sim.center_frequency())) / 2) Coax( sim=sim, position=Coordinate3(0, 0, 0), length=length, radius=coax_rad, core_radius=core_rad,
#!/usr/bin/env python3 import numpy as np from pyems.pcb import common_pcbs from pyems.structure import PCB, Microstrip from pyems.coordinate import Box2, Coordinate2, Axis from pyems.mesh import Mesh from pyems.simulation import Simulation from pyems.calc import sweep from pyems.utilities import mil_to_mm, array_index, print_table freq = np.linspace(4e9, 8e9, 501) sim = Simulation(freq=freq, unit=1e-3) pcb_prop = common_pcbs["oshpark4"] pcb_len = 30 pcb_width = 10 z0_target = 50 width_dev_factor = 0.1 center_width = 0.34 gap = mil_to_mm(6) via_gap = 0.4 num_points = 1 # num_points = 31 def sim_impedance(sim: Simulation): """ Get the characteristic impedance of a simulation. """ sim.run(csx=False) ports = sim.ports