Example #1
0
 def __init__(self, name, fmin=0, fmax=50e9,
              NrTS=1e6,
              EndCriteria=1e-6,
              #BC = {xmin xmax ymin ymax zmin zmax};
              boundaries = ['PEC', 'PEC', 'PEC', 'PEC', 'PEC', 'PEC'],
              fsteps = 1601
 ):
     self.FDTD = openEMS(NrTS=NrTS, EndCriteria=EndCriteria)
     self.FDTD.SetGaussExcite((fmin+fmax)/2.0, (fmax-fmin)/2.0)
     self.FDTD.SetBoundaryCond(boundaries)
     self.CSX = ContinuousStructure()
     self.FDTD.SetCSX(self.CSX)
     self.mesh = self.CSX.GetGrid()
     self.mesh.SetDeltaUnit(1.0) # specify everything in m
     self.fmin = fmin
     self.fmax = fmax
     self.fsteps = fsteps
     self.objects = {}
     self.name = name
     self.ports = []
     self.excitation_port = 0
     self.excite_ports = [1]
     self.via_offset_x = 0.0
     self.via_offset_y = 0.0
     self.xgrid = None # for plot
     self.ygrid = None
     self.legend_location = 2 # upper left
     self.options = ''
     self.name_count = 0
     self.resolution = 0.0001
Example #2
0
    feed_length = 30000

    substrate_thickness = [1524, 101, 254]
    substrate_epsr = [3.48, 3.48, 3.48]

    CRLH = CRLH_Cells(LL  = 14e3, LW  = 4e3, GLB = 1950, GLT = 4700, SL  = 7800, SW  = 1000, VR  = 250 , \
                      Top = sum(substrate_thickness), \
                      Bot = sum(substrate_thickness[:-1]))

    # frequency range of interest
    f_start = 0.8e9
    f_stop = 6e9

    ### Setup FDTD parameters & excitation function
    CSX = ContinuousStructure()
    FDTD = openEMS(EndCriteria=1e-5)
    FDTD.SetCSX(CSX)
    mesh = CSX.GetGrid()
    mesh.SetDeltaUnit(unit)

    CRLH.createProperties(CSX)

    FDTD.SetGaussExcite((f_start + f_stop) / 2, (f_stop - f_start) / 2)
    BC = {'PML_8' 'PML_8' 'MUR' 'MUR' 'PEC' 'PML_8'}
    FDTD.SetBoundaryCond(['PML_8', 'PML_8', 'MUR', 'MUR', 'PEC', 'PML_8'])

    ### Setup a basic mesh and create the CRLH unit cell
    resolution = C0 / (f_stop * sqrt(
        max(substrate_epsr))) / unit / 30  # resolution of lambda/30
    CRLH.setEdgeResolution(resolution / 4)
Example #3
0
class OpenEMS:
    def __init__(self, name, fmin=0, fmax=50e9,
                 NrTS=1e6,
                 EndCriteria=1e-6,
                 #BC = {xmin xmax ymin ymax zmin zmax};
                 boundaries = ['PEC', 'PEC', 'PEC', 'PEC', 'PEC', 'PEC'],
                 fsteps = 1601
    ):
        self.FDTD = openEMS(NrTS=NrTS, EndCriteria=EndCriteria)
        self.FDTD.SetGaussExcite((fmin+fmax)/2.0, (fmax-fmin)/2.0)
        self.FDTD.SetBoundaryCond(boundaries)
        self.CSX = ContinuousStructure()
        self.FDTD.SetCSX(self.CSX)
        self.mesh = self.CSX.GetGrid()
        self.mesh.SetDeltaUnit(1.0) # specify everything in m
        self.fmin = fmin
        self.fmax = fmax
        self.fsteps = fsteps
        self.objects = {}
        self.name = name
        self.ports = []
        self.excitation_port = 0
        self.excite_ports = [1]
        self.via_offset_x = 0.0
        self.via_offset_y = 0.0
        self.xgrid = None # for plot
        self.ygrid = None
        self.legend_location = 2 # upper left
        self.options = ''
        self.name_count = 0
        self.resolution = 0.0001

    def AddPort(self, start, stop, direction, z):
        return Port(self, start, stop, direction, z)

    def get_name(self, name):
        if name:
            return name
        self.name_count += 1
        return "pad_{}".format(self.name_count)

    def write_kicad(self, fpname, mirror=""):
        g = kicadfpwriter.Generator(fpname)
        g.mirror = mirror
        for object in self.objects:
            g.drill = 0
            self.objects[object].generate_kicad(g)
        fp = g.finish()
        with open(self.name+".kicad_mod", "w") as f:
            f.write(fp)

    def run_openems(self, options='view solve', z=50, initialize=True):
        cwd = os.getcwd()
        basename = cwd + '/' + self.name
        simpath = r'/tmp/openems_data'
        if not os.path.exists(simpath):
            os.mkdir(simpath)

        for object in self.objects:
            self.objects[object].generate_octave()

        import collections
        if not isinstance(self.resolution, collections.Sequence):
            self.resolution = np.ones(3) * self.resolution

        ratio = 1.5
        for i in range(3):
            if self.resolution[i] is not None:
                self.mesh.SmoothMeshLines('xyz'[i], self.resolution[i], ratio)

        if 'view' in options:
                CSX_file = simpath + '/csx.xml'
                self.CSX.Write2XML(CSX_file)
                os.system(r'AppCSXCAD "{}"'.format(CSX_file))
        if 'solve' in options:
            self.FDTD.Run(simpath, verbose=3, cleanup=True)
            f = np.linspace(self.fmin, self.fmax, self.fsteps)
            for p in self.ports:
                p.port.CalcPort(simpath, f, ref_impedance = z)
            nports = len(self.ports)

            s = []

            for p in range(nports):
                s.append(self.ports[p].port.uf_ref / self.ports[0].port.uf_inc)

            if nports < 1:
                return

            self.frequencies = f
            fig, ax = matplotlib.pyplot.subplots()
            s11 = s[0]
            if nports == 1:
                save_s1p(f, s11, basename+".s1p", z=z)
            if nports > 1:
                s21 = s[1]
                ax.plot(f/1e9, 20*np.log10(np.abs(s21)), label = 'dB(s21)')
                save_s2p_symmetric(f, s11, s21, basename+".s2p", z=z)
            ax.plot(f/1e9, 20*np.log10(np.abs(s11)), label = 'dB(s11)')
            if nports > 2:
                s31 = s[2]
                ax.plot(f/1e9, 20*np.log10(np.abs(s31)), label = 'dB(s31)')
            if nports > 3:
                s41 = s[3]
                ax.plot(f/1e9, 20*np.log10(np.abs(s41)), label = 'dB(s41)')

            ax.set_xlabel('Frequency (GHz)')
            ax.set_ylabel('dB')
            if hasattr(self.xgrid, "__len__"):
                ax.set_xticks(self.xgrid)
            if hasattr(self.ygrid, "__len__"):
                ax.set_yticks(self.ygrid)
            ax.grid(True)
            fig.tight_layout()
            ax.legend(loc=self.legend_location)
            matplotlib.pyplot.savefig(basename+".png")
            matplotlib.pyplot.savefig(basename+".svg")
            matplotlib.pyplot.savefig(basename+".pdf")
            matplotlib.pyplot.show()
# size of the simulation box
SimBox = np.array([200, 200, 150])

# setup FDTD parameter & excitation function
f0 = 2e9  # center frequency
fc = 1e9  # 20 dB corner frequency

### FDTD setup
## * Limit the simulation to 30k timesteps
## * Define a reduced end criteria of -40dB
FDTD = openEMS(NrTS=30000, EndCriteria=1e-4)
FDTD.SetGaussExcite(f0, fc)
FDTD.SetBoundaryCond(['MUR', 'MUR', 'MUR', 'MUR', 'MUR', 'MUR'])

CSX = ContinuousStructure()
FDTD.SetCSX(CSX)
mesh = CSX.GetGrid()
mesh.SetDeltaUnit(1e-3)
mesh_res = C0 / (f0 + fc) / 1e-3 / 20

### Generate properties, primitives and mesh-grid
#initialize the mesh with the "air-box" dimensions
mesh.AddLine('x', [-SimBox[0] / 2, SimBox[0] / 2])
mesh.AddLine('y', [-SimBox[1] / 2, SimBox[1] / 2])
mesh.AddLine('z', [-SimBox[2] / 3, SimBox[2] * 2 / 3])

# create patch
patch = CSX.AddMetal('patch')  # create a perfect electric conductor (PEC)
start = [-patch_width / 2, -patch_length / 2, substrate_thickness]
stop = [patch_width / 2, patch_length / 2, substrate_thickness]
Example #5
0
# size of the simulation box
SimBox = 1200
PW_Box = 750

### Setup FDTD parameters & excitation function
FDTD = openEMS(EndCriteria=1e-5)

f_start = 50e6  # start frequency
f_stop = 1000e6  # stop  frequency
f0 = 500e6
FDTD.SetGaussExcite(0.5 * (f_start + f_stop), 0.5 * (f_stop - f_start))

FDTD.SetBoundaryCond(['PML_8', 'PML_8', 'PML_8', 'PML_8', 'PML_8', 'PML_8'])

### Setup Geometry & Mesh
CSX = ContinuousStructure()
FDTD.SetCSX(CSX)
mesh = CSX.GetGrid()
mesh.SetDeltaUnit(unit)

#create mesh
mesh.SetLines('x', [-SimBox / 2, 0, SimBox / 2])
mesh.SmoothMeshLines('x', C0 / f_stop / unit / 20)  # cell size: lambda/20
mesh.SetLines('y', mesh.GetLines('x'))
mesh.SetLines('z', mesh.GetLines('x'))

### Create a metal sphere and plane wave source
sphere_metal = CSX.AddMetal(
    'sphere')  # create a perfect electric conductor (PEC)
sphere_metal.AddSphere(priority=10, center=[0, 0, 0], radius=sphere_rad)
Example #6
0
class OpenEMS:
    def __init__(
            self,
            name,
            fmin=0,
            fmax=50e9,
            NrTS=1e6,
            EndCriteria=1e-6,
            #BC = {xmin xmax ymin ymax zmin zmax};
            boundaries=['PEC', 'PEC', 'PEC', 'PEC', 'PEC', 'PEC'],
            fsteps=1601):
        self.FDTD = openEMS(NrTS=NrTS, EndCriteria=EndCriteria)
        self.FDTD.SetGaussExcite((fmin + fmax) / 2.0, (fmax - fmin) / 2.0)
        self.FDTD.SetBoundaryCond(boundaries)
        self.CSX = ContinuousStructure()
        self.FDTD.SetCSX(self.CSX)
        self.mesh = self.CSX.GetGrid()
        self.mesh.SetDeltaUnit(1.0)  # specify everything in m
        self.fmin = fmin
        self.fmax = fmax
        self.fsteps = fsteps
        self.objects = {}
        self.name = name
        self.ports = []
        self.excitation_port = 0
        self.excite_ports = [1]
        self.metalloss = False
        self.via_offset_x = 0.0
        self.via_offset_y = 0.0
        self.xgrid = None  # for plot
        self.ygrid = None
        self.legend_location = 2  # upper left
        self.options = ''
        self.name_count = 0
        self.resolution = 0.0001

    def AddPort(self, start, stop, direction, z):
        return Port(self, start, stop, direction, z)

    def add_resistor(self,
                     name,
                     origin=np.array([0, 0, 0]),
                     direction='x',
                     value=100.0,
                     invert=False,
                     priority=9,
                     dielectric=None,
                     metal=None,
                     element_down=False,
                     size='0201'):
        """ currently only supports 'x', 'y' for direction """
        element = LumpedElement(self,
                                name,
                                element_type='R',
                                value=value,
                                direction=direction)
        # resistor end caps
        start = np.array([-0.15 * mm, -0.3 * mm, 0])
        stop = np.array([0.15 * mm, -0.25 * mm / 2, 0.25 * mm])
        if size == '0402':
            start = np.array([-0.25 * mm, -0.5 * mm, 0])
            stop = np.array([0.25 * mm, -0.5 * mm / 2, 0.35 * mm])
        for m in [np.array([1, -1, 1]), np.array([1, 1, 1])]:
            metal.AddBox(origin + start * m,
                         origin + stop * m,
                         priority=priority,
                         padname=None)
        # resistor body
        start = np.array([-0.15, -0.27, 0.02]) * mm
        stop = np.array([0.15, 0.27, 0.23]) * mm
        if size == '0402':
            start = np.array([-0.25, -0.47, 0.02]) * mm
            stop = np.array([0.25, 0.47, 0.33]) * mm
        body = dielectric.AddBox(origin + start,
                                 origin + stop,
                                 priority=priority + 1,
                                 padname=None)
        # resistor element
        if element_down:
            zoff = 0.0
        else:
            zoff = 0.33 if size == '0402' else 0.23
        start = np.array([-0.1, -0.25 / 2, 0 + zoff]) * mm
        stop = np.array([0.1, 0.25 / 2, 0.02 + zoff]) * mm
        if size == '0402':
            start = np.array([-0.2, -0.25, 0 + zoff]) * mm
            stop = np.array([0.2, 0.25, 0.02 + zoff]) * mm
        start += origin
        stop += origin
        element = element.AddBox(start,
                                 stop,
                                 priority=priority + 1,
                                 padname=None)
        # reposition
        if invert:
            cap1.mirror('z')
            cap2.mirror('z')
            body.mirror('z')
            element.mirror('z')
        if not 'y' in direction:
            cap1.rotate_ccw_90()
            cap2.rotate_ccw_90()
            body.rotate_ccw_90()
            element.rotate_ccw_90()

    def get_name(self, name):
        if name:
            return name
        self.name_count += 1
        return "pad_{}".format(self.name_count)

    def write_kicad(self, fpname, mirror=""):
        g = kicadfpwriter.Generator(fpname)
        g.mirror = mirror
        for object in self.objects:
            g.drill = 0
            self.objects[object].generate_kicad(g)
        fp = g.finish()
        with open(self.name + ".kicad_mod", "w") as f:
            f.write(fp)

    def run_openems(self, options='view solve', z=50):
        cwd = os.getcwd()
        basename = cwd + '/' + self.name
        simpath = r'/tmp/openems_data'
        if not os.path.exists(simpath):
            os.mkdir(simpath)

        for object in self.objects:
            self.objects[object].generate_octave()

        import collections
        if not isinstance(self.resolution, collections.Sequence):
            self.resolution = np.ones(3) * self.resolution

        ratio = 1.5
        self.mesh.SmoothMeshLines('x', self.resolution[0], ratio)
        self.mesh.SmoothMeshLines('y', self.resolution[1], ratio)
        self.mesh.SmoothMeshLines('z', self.resolution[2], ratio)

        if 'view' in options:
            CSX_file = simpath + '/csx.xml'
            self.CSX.Write2XML(CSX_file)
            os.system(r'AppCSXCAD "{}"'.format(CSX_file))
        if 'solve' in options:
            self.FDTD.Run(simpath, verbose=3, cleanup=True)
            f = np.linspace(self.fmin, self.fmax, self.fsteps)
            for p in self.ports:
                p.port.CalcPort(simpath, f, ref_impedance=z)
            nports = len(self.ports)

            s = []

            for p in range(nports):
                s.append(self.ports[p].port.uf_ref / self.ports[0].port.uf_inc)

            if nports < 1:
                return

            self.frequencies = f
            fig, ax = matplotlib.pyplot.subplots()
            s11 = s[0]
            if nports == 1:
                save_s1p(f, s11, basename + ".s1p", z=z)
            if nports > 1:
                s21 = s[1]
                ax.plot(f / 1e9, 20 * np.log10(np.abs(s21)), label='dB(s21)')
                save_s2p_symmetric(f, s11, s21, basename + ".s2p", z=z)
            ax.plot(f / 1e9, 20 * np.log10(np.abs(s11)), label='dB(s11)')
            if nports > 2:
                s31 = s[2]
                ax.plot(f / 1e9, 20 * np.log10(np.abs(s31)), label='dB(s31)')
            if nports > 3:
                s41 = s[3]
                ax.plot(f / 1e9, 20 * np.log10(np.abs(s41)), label='dB(s41)')

            ax.set_xlabel('Frequency (GHz)')
            ax.set_ylabel('dB')
            if hasattr(self.xgrid, "__len__"):
                ax.set_xticks(self.xgrid)
            if hasattr(self.ygrid, "__len__"):
                ax.set_yticks(self.ygrid)
            ax.grid(True)
            fig.tight_layout()
            ax.legend(loc=self.legend_location)
            matplotlib.pyplot.savefig(basename + ".png")
            matplotlib.pyplot.savefig(basename + ".svg")
            matplotlib.pyplot.savefig(basename + ".pdf")
            matplotlib.pyplot.show()
            print(len(self.frequencies))
            print(s)
Example #7
0
unit = 1e-6  # specify everything in um
MSL_length = 50000
MSL_width = 600
substrate_thickness = 254
substrate_epr = 3.66
stub_length = 12e3
f_max = 7e9

### Setup FDTD parameters & excitation function
FDTD = openEMS()
FDTD.SetGaussExcite(f_max / 2, f_max / 2)
FDTD.SetBoundaryCond(['PML_8', 'PML_8', 'MUR', 'MUR', 'PEC', 'MUR'])

### Setup Geometry & Mesh
CSX = ContinuousStructure()
FDTD.SetCSX(CSX)
mesh = CSX.GetGrid()
mesh.SetDeltaUnit(unit)

resolution = C0 / (f_max *
                   sqrt(substrate_epr)) / unit / 50  # resolution of lambda/50
third_mesh = array([2 * resolution / 3, -resolution / 3]) / 4

## Do manual meshing
mesh.AddLine('x', 0)
mesh.AddLine('x', MSL_width / 2 + third_mesh)
mesh.AddLine('x', -MSL_width / 2 - third_mesh)
mesh.SmoothMeshLines('x', resolution / 4)

mesh.AddLine('x', [-MSL_length, MSL_length])
Example #8
0
#waveguide TE-mode definition
TE_mode = 'TE10'

#targeted mesh resolution
mesh_res = lambda0 / 30

### Setup FDTD parameter & excitation function
FDTD = openEMS(NrTS=1e4)
FDTD.SetGaussExcite(0.5 * (f_start + f_stop), 0.5 * (f_stop - f_start))

# boundary conditions
FDTD.SetBoundaryCond([0, 0, 0, 0, 3, 3])

### Setup geometry & mesh
CSX = ContinuousStructure()
FDTD.SetCSX(CSX)
mesh = CSX.GetGrid()
mesh.SetDeltaUnit(unit)

mesh.AddLine('x', [0, a])
mesh.AddLine('y', [0, b])
mesh.AddLine('z', [0, length])

## Apply the waveguide port
ports = []
start = [0, 0, 10 * mesh_res]
stop = [a, b, 15 * mesh_res]
mesh.AddLine('z', [start[2], stop[2]])
ports.append(
    FDTD.AddRectWaveGuidePort(0, start, stop, 'z', a * unit, b * unit, TE_mode,