Add XSPICE models for transmission lines
This commit is contained in:
parent
f656b73240
commit
e82519388e
|
|
@ -25,6 +25,7 @@ if $?xspice_enabled
|
||||||
@XSPICEINIT@ codemodel @pkglibdir@/xtradev.cm
|
@XSPICEINIT@ codemodel @pkglibdir@/xtradev.cm
|
||||||
@XSPICEINIT@ codemodel @pkglibdir@/xtraevt.cm
|
@XSPICEINIT@ codemodel @pkglibdir@/xtraevt.cm
|
||||||
@XSPICEINIT@ codemodel @pkglibdir@/table.cm
|
@XSPICEINIT@ codemodel @pkglibdir@/table.cm
|
||||||
|
@XSPICEINIT@ codemodel @pkglibdir@/tlines.cm
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ include makedefs
|
||||||
|
|
||||||
|
|
||||||
# The codemodels to make
|
# The codemodels to make
|
||||||
CMDIRS = spice2poly digital analog xtradev xtraevt table
|
CMDIRS = spice2poly digital analog xtradev xtraevt table tlines
|
||||||
|
|
||||||
|
|
||||||
#Invoke $(MAKE) for each of the CMDDIRS
|
#Invoke $(MAKE) for each of the CMDDIRS
|
||||||
all: dstring.o # One common dstring object file for all code modules
|
all: dstring.o msline_common.o tline_common.o# Common object files for all code modules
|
||||||
for cm in $(CMDIRS) ; do \
|
for cm in $(CMDIRS) ; do \
|
||||||
$(MAKE) cm=$$cm $$cm/$$cm.cm \
|
$(MAKE) cm=$$cm $$cm/$$cm.cm \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
|
|
@ -36,6 +36,8 @@ uninstall:
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f dstring.o
|
rm -f dstring.o
|
||||||
|
rm -f msline_common.o
|
||||||
|
rm -f tline_common.o
|
||||||
for cm in $(CMDIRS) ; do \
|
for cm in $(CMDIRS) ; do \
|
||||||
$(MAKE) cm=$$cm cm-clean \
|
$(MAKE) cm=$$cm cm-clean \
|
||||||
|| exit 1; \
|
|| exit 1; \
|
||||||
|
|
@ -49,6 +51,12 @@ NGSRCBUILDDIR = $(CURDIR)/../..
|
||||||
dstring.o: $(NGSRCDIR)/misc/dstring.c $(NGSRCDIR)/include/ngspice/dstring.h
|
dstring.o: $(NGSRCDIR)/misc/dstring.c $(NGSRCDIR)/include/ngspice/dstring.h
|
||||||
$(CC) $(CFLAGS) -I$(NGSRCDIR)/include -I$(NGSRCBUILDDIR)/include -fPIC -o $@ -c $<
|
$(CC) $(CFLAGS) -I$(NGSRCDIR)/include -I$(NGSRCBUILDDIR)/include -fPIC -o $@ -c $<
|
||||||
|
|
||||||
|
msline_common.o: $(srcdir)/../tlines/msline_common.c $(srcdir)/../tlines/msline_common.h
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir)/../tlines -I$(NGSRCDIR)/include -I$(NGSRCBUILDDIR)/include -fPIC -o $@ -c $<
|
||||||
|
|
||||||
|
tline_common.o: $(srcdir)/../tlines/tline_common.c $(srcdir)/../tlines/tline_common.h
|
||||||
|
$(CC) $(CFLAGS) -I$(srcdir)/../tlines -I$(NGSRCDIR)/include -I$(NGSRCBUILDDIR)/include -fPIC -o $@ -c $<
|
||||||
|
|
||||||
ifdef cm
|
ifdef cm
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT)
|
ifeq ($(OS),Windows_NT)
|
||||||
|
|
@ -70,6 +78,8 @@ cm-gens := \
|
||||||
cm-objs := \
|
cm-objs := \
|
||||||
$(cm)/dlmain.o \
|
$(cm)/dlmain.o \
|
||||||
dstring.o \
|
dstring.o \
|
||||||
|
tline_common.o \
|
||||||
|
msline_common.o \
|
||||||
$(modlst:%=$(cm)/%/cfunc.o) \
|
$(modlst:%=$(cm)/%/cfunc.o) \
|
||||||
$(modlst:%=$(cm)/%/ifspec.o) \
|
$(modlst:%=$(cm)/%/ifspec.o) \
|
||||||
$(udnlst:%=$(cm)/%/udnfunc.o)
|
$(udnlst:%=$(cm)/%/udnfunc.o)
|
||||||
|
|
@ -160,11 +170,11 @@ $(cm)/dlmain.o : $(srcdir)/dlmain.c $(cm-descr)
|
||||||
$(do-deps)
|
$(do-deps)
|
||||||
|
|
||||||
$(cm)/%/cfunc.o : $(cm)/%/cfunc.c
|
$(cm)/%/cfunc.o : $(cm)/%/cfunc.c
|
||||||
$(COMPILE) $(gen_pp) -I$(srcdir)/$(<D) -o $@ -c $<
|
$(COMPILE) $(gen_pp) -I$(srcdir)/$(<D) -I$(srcdir)/../tlines -o $@ -c $<
|
||||||
$(do-deps)
|
$(do-deps)
|
||||||
|
|
||||||
$(cm)/%/ifspec.o : $(cm)/%/ifspec.c
|
$(cm)/%/ifspec.o : $(cm)/%/ifspec.c
|
||||||
$(COMPILE) $(gen_pp) -I$(srcdir)/$(<D) -o $@ -c $<
|
$(COMPILE) $(gen_pp) -I$(srcdir)/$(<D) -I$(srcdir)/../tlines -o $@ -c $<
|
||||||
$(do-deps)
|
$(do-deps)
|
||||||
|
|
||||||
$(cm)/%/udnfunc.o : $(srcdir)/$(cm)/%/udnfunc.c
|
$(cm)/%/udnfunc.o : $(srcdir)/$(cm)/%/udnfunc.c
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE cfunc.mod
|
||||||
|
|
||||||
|
(c) Vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <complex.h>
|
||||||
|
|
||||||
|
#include "msline_common.h"
|
||||||
|
#include "tline_common.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void copy_complex(double complex s, Complex_t *d)
|
||||||
|
{
|
||||||
|
d->real = creal(s);
|
||||||
|
d->imag = cimag(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
cpline_state_t *sim_points = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void cm_cpline (ARGS)
|
||||||
|
{
|
||||||
|
Complex_t z11, z12, z13, z14;
|
||||||
|
|
||||||
|
/* how to get properties of this component, e.g. L, W */
|
||||||
|
double l = PARAM(l);
|
||||||
|
double ze = PARAM(ze);
|
||||||
|
double zo = PARAM(zo);
|
||||||
|
double ere = PARAM(ere);
|
||||||
|
double ero = PARAM(ero);
|
||||||
|
double ae = PARAM(ae);
|
||||||
|
double ao = PARAM(ao);
|
||||||
|
ae = pow(10, 0.05*ae);
|
||||||
|
ao = pow(10, 0.05*ao);
|
||||||
|
|
||||||
|
if(INIT) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the output */
|
||||||
|
if(ANALYSIS == DC) {
|
||||||
|
|
||||||
|
double V1 = INPUT(p1s);
|
||||||
|
double V2 = INPUT(p2s);
|
||||||
|
double V3 = INPUT(p3s);
|
||||||
|
double V4 = INPUT(p4s);
|
||||||
|
double I1 = INPUT(p1);
|
||||||
|
double I2 = INPUT(p2);
|
||||||
|
double I3 = INPUT(p3);
|
||||||
|
double I4 = INPUT(p4);
|
||||||
|
|
||||||
|
double z = sqrt(ze*zo);
|
||||||
|
|
||||||
|
double V2out = V1 + z*I1;
|
||||||
|
double V1out = V2 + z*I2;
|
||||||
|
OUTPUT(p1) = V1out + I1*z;
|
||||||
|
OUTPUT(p2) = V2out + I2*z;
|
||||||
|
|
||||||
|
double V3out = V4 + z*I4;
|
||||||
|
double V4out = V3 + z*I3;
|
||||||
|
OUTPUT(p3) = V3out + I3*z;
|
||||||
|
OUTPUT(p4) = V4out + I4*z;
|
||||||
|
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == AC) {
|
||||||
|
double o = RAD_FREQ;
|
||||||
|
|
||||||
|
double complex _Z11, _Z12, _Z13, _Z14;
|
||||||
|
double complex arg_e = log(ae)*l/2.0 + I*o*l/C0*sqrt(ere);
|
||||||
|
double complex arg_o = log(ao)*l/2.0 + I*o*l/C0*sqrt(ero);
|
||||||
|
|
||||||
|
_Z11 = zo / (2*ctanh(arg_o)) + ze / (2*ctanh(arg_e));
|
||||||
|
_Z12 = zo / (2*csinh(arg_o)) + ze / (2*csinh(arg_e));
|
||||||
|
_Z13 = ze / (2*csinh(arg_e)) - zo / (2*csinh(arg_o));
|
||||||
|
_Z14 = ze / (2*ctanh(arg_e)) - zo / (2*ctanh(arg_o));
|
||||||
|
|
||||||
|
copy_complex(_Z11,&z11);
|
||||||
|
copy_complex(_Z12,&z12);
|
||||||
|
copy_complex(_Z13,&z13);
|
||||||
|
copy_complex(_Z14,&z14);
|
||||||
|
|
||||||
|
AC_GAIN(p1,p1) = z11; AC_GAIN(p2,p2) = z11;
|
||||||
|
AC_GAIN(p3,p3) = z11; AC_GAIN(p4,p4) = z11;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p2) = z12; AC_GAIN(p2,p1) = z12;
|
||||||
|
AC_GAIN(p3,p4) = z12; AC_GAIN(p4,p3) = z12;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p3) = z13; AC_GAIN(p3,p1) = z13;
|
||||||
|
AC_GAIN(p2,p4) = z13; AC_GAIN(p4,p2) = z13;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p4) = z14; AC_GAIN(p4,p1) = z14;
|
||||||
|
AC_GAIN(p2,p3) = z14; AC_GAIN(p3,p2) = z14;
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == TRANSIENT) {
|
||||||
|
double t = TIME;
|
||||||
|
double Vp[PORT_NUM];
|
||||||
|
double Ip[PORT_NUM];
|
||||||
|
|
||||||
|
Vp[0] = INPUT(p1s);
|
||||||
|
Vp[1] = INPUT(p2s);
|
||||||
|
Vp[2] = INPUT(p3s);
|
||||||
|
Vp[3] = INPUT(p4s);
|
||||||
|
Ip[0] = INPUT(p1);
|
||||||
|
Ip[1] = INPUT(p2);
|
||||||
|
Ip[2] = INPUT(p3);
|
||||||
|
Ip[3] = INPUT(p4);
|
||||||
|
double delay = l/(C0);
|
||||||
|
append_cpline_state(&sim_points, t, Vp, Ip, 1.2*delay);
|
||||||
|
if (t > delay) {
|
||||||
|
cpline_state_t *pp = find_cpline_state(sim_points, t - delay);
|
||||||
|
if (pp != NULL) {
|
||||||
|
|
||||||
|
double J1e = 0.5*(Ip[3] + Ip[0]);
|
||||||
|
double J1o = 0.5*(Ip[0] - Ip[3]);
|
||||||
|
double J2e = 0.5*(Ip[1] + Ip[2]);
|
||||||
|
double J2o = 0.5*(Ip[1] - Ip[2]);
|
||||||
|
|
||||||
|
|
||||||
|
double J1et = 0.5*(pp->Ip[3] + pp->Ip[0]);
|
||||||
|
double J1ot = 0.5*(pp->Ip[0] - pp->Ip[3]);
|
||||||
|
double J2et = 0.5*(pp->Ip[1] + pp->Ip[2]);
|
||||||
|
double J2ot = 0.5*(pp->Ip[1] - pp->Ip[2]);
|
||||||
|
|
||||||
|
|
||||||
|
double V1et = 0.5*(pp->Vp[3] + pp->Vp[0]);
|
||||||
|
double V1ot = 0.5*(pp->Vp[0] - pp->Vp[3]);
|
||||||
|
double V2et = 0.5*(pp->Vp[1] + pp->Vp[2]);
|
||||||
|
double V2ot = 0.5*(pp->Vp[1] - pp->Vp[2]);
|
||||||
|
|
||||||
|
double V1e = ze*J1e + V2et + ze*J2et;
|
||||||
|
double V1o = zo*J1o + V2ot + zo*J2ot;
|
||||||
|
double V2e = ze*J2e + V1et + ze*J1et;
|
||||||
|
double V2o = zo*J2o + V1ot + zo*J1ot;
|
||||||
|
|
||||||
|
double V1 = V1o + V1e;
|
||||||
|
double V2 = V2o + V2e;
|
||||||
|
double V3 = V2e - V2o;
|
||||||
|
double V4 = V1e - V1o;
|
||||||
|
|
||||||
|
OUTPUT(p1) = V1;
|
||||||
|
OUTPUT(p2) = V2;
|
||||||
|
OUTPUT(p3) = V3;
|
||||||
|
OUTPUT(p4) = V4;
|
||||||
|
}
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
} else {
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE ifspec.ifs
|
||||||
|
|
||||||
|
(c) vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
=========================================================================== */
|
||||||
|
|
||||||
|
/* Ports connection
|
||||||
|
4 --||||||-- 3
|
||||||
|
|
||||||
|
1 --||||||-- 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
NAME_TABLE:
|
||||||
|
|
||||||
|
Spice_Model_Name: cpline
|
||||||
|
C_Function_Name: cm_cpline
|
||||||
|
Description: "Generic transmission line"
|
||||||
|
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p1
|
||||||
|
Description: "Terminals Line1"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p2
|
||||||
|
Description: "Terminals Line1"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p3
|
||||||
|
Description: "Terminals Line2"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p4
|
||||||
|
Description: "Terminals Line2"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p1s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p2s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p3s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p4s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: l
|
||||||
|
Description: "length"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: ze
|
||||||
|
Description: "characteristic impedance of even mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 50.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: zo
|
||||||
|
Description: "characteristic impedance of odd mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 50.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: ae
|
||||||
|
Description: "attenuation per length (dB) even mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: ao
|
||||||
|
Description: "attenuation per length (dB) odd mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: ere
|
||||||
|
Description: "dielectric constant even mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: ero
|
||||||
|
Description: "dielectric constant odd mode"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,496 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE cfunc.mod
|
||||||
|
|
||||||
|
(c) Vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <complex.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "msline_common.h"
|
||||||
|
#include "tline_common.h"
|
||||||
|
|
||||||
|
static double ae, ao, be, bo, ze, zo, ee, eo;
|
||||||
|
|
||||||
|
static void copy_complex(double complex s, Complex_t *d)
|
||||||
|
{
|
||||||
|
d->real = creal(s);
|
||||||
|
d->imag = cimag(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static cpline_state_t *state = NULL;
|
||||||
|
|
||||||
|
static void analyseQuasiStatic (double W, double h, double s,
|
||||||
|
double t, double er,
|
||||||
|
int SModel, double* Zle,
|
||||||
|
double* Zlo, double* ErEffe,
|
||||||
|
double* ErEffo);
|
||||||
|
|
||||||
|
static void analyseDispersion (double W, double h, double s,
|
||||||
|
double t, double er, double Zle,
|
||||||
|
double Zlo, double ErEffe,
|
||||||
|
double ErEffo, double frequency,
|
||||||
|
int DModel, double *ZleFreq,
|
||||||
|
double *ZloFreq,
|
||||||
|
double *ErEffeFreq,
|
||||||
|
double *ErEffoFreq);
|
||||||
|
|
||||||
|
static void calcPropagation (double W, double s,
|
||||||
|
double er, double h, double t, double tand, double rho, double D,
|
||||||
|
int SModel, int DModel, double frequency)
|
||||||
|
{
|
||||||
|
|
||||||
|
// quasi-static analysis
|
||||||
|
double Zle, ErEffe, Zlo, ErEffo;
|
||||||
|
analyseQuasiStatic (W, h, s, t, er, SModel, &Zle, &Zlo, &ErEffe, &ErEffo);
|
||||||
|
|
||||||
|
// analyse dispersion of Zl and Er
|
||||||
|
double ZleFreq, ErEffeFreq, ZloFreq, ErEffoFreq;
|
||||||
|
analyseDispersion (W, h, s, t, er, Zle, Zlo, ErEffe, ErEffo, frequency, DModel,
|
||||||
|
&ZleFreq, &ZloFreq, &ErEffeFreq, &ErEffoFreq);
|
||||||
|
|
||||||
|
// analyse losses of line
|
||||||
|
double ace, aco, ade, ado;
|
||||||
|
analyseLoss (W, t, er, rho, D, tand, Zle, Zlo, ErEffe,
|
||||||
|
frequency, HAMMERSTAD, &ace, &ade);
|
||||||
|
analyseLoss (W, t, er, rho, D, tand, Zlo, Zle, ErEffo,
|
||||||
|
frequency, HAMMERSTAD, &aco, &ado);
|
||||||
|
|
||||||
|
// compute propagation constants for even and odd mode
|
||||||
|
double k0 = 2 * M_PI * frequency / C0;
|
||||||
|
ae = ace + ade;
|
||||||
|
ao = aco + ado;
|
||||||
|
be = sqrt (ErEffeFreq) * k0;
|
||||||
|
bo = sqrt (ErEffoFreq) * k0;
|
||||||
|
ze = ZleFreq;
|
||||||
|
zo = ZloFreq;
|
||||||
|
ee = ErEffeFreq;
|
||||||
|
eo = ErEffoFreq;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The function calculates the quasi-static dielectric constants and
|
||||||
|
characteristic impedances for the even and odd mode based upon the
|
||||||
|
given line and substrate properties for parallel coupled microstrip
|
||||||
|
lines. */
|
||||||
|
static void analyseQuasiStatic (double W, double h, double s,
|
||||||
|
double t, double er,
|
||||||
|
int SModel, double* Zle,
|
||||||
|
double* Zlo, double* ErEffe,
|
||||||
|
double* ErEffo) {
|
||||||
|
// initialize default return values
|
||||||
|
*ErEffe = er; *ErEffo = er;
|
||||||
|
*Zlo = 42.2; *Zle = 55.7;
|
||||||
|
|
||||||
|
// normalized width and gap
|
||||||
|
double u = W / h;
|
||||||
|
double g = s / h;
|
||||||
|
|
||||||
|
// HAMMERSTAD and JENSEN
|
||||||
|
if (SModel == HAMMERSTAD) {
|
||||||
|
double Zl1, Fe, Fo, a, b, fo, Mu, Alpha, Beta, ErEff;
|
||||||
|
double Pe, Po, r, fo1, q, p, n, Psi, Phi, m, Theta;
|
||||||
|
|
||||||
|
// modifying equations for even mode
|
||||||
|
m = 0.2175 + pow (4.113 + pow (20.36 / g, 6.), -0.251) +
|
||||||
|
log (pow (g, 10.) / (1 + pow (g / 13.8, 10.))) / 323;
|
||||||
|
Alpha = 0.5 * exp (-g);
|
||||||
|
Psi = 1 + g / 1.45 + pow (g, 2.09) / 3.95;
|
||||||
|
Phi = 0.8645 * pow (u, 0.172);
|
||||||
|
Pe = Phi / (Psi * (Alpha * pow (u, m) + (1 - Alpha) * pow (u, -m)));
|
||||||
|
// TODO: is this ... Psi * (Alpha ... or ... Psi / (Alpha ... ?
|
||||||
|
|
||||||
|
// modifying equations for odd mode
|
||||||
|
n = (1 / 17.7 + exp (-6.424 - 0.76 * log (g) - pow (g / 0.23, 5.))) *
|
||||||
|
log ((10 + 68.3 * sqr (g)) / (1 + 32.5 * pow (g, 3.093)));
|
||||||
|
Beta = 0.2306 + log (pow (g, 10.) / (1 + pow (g / 3.73, 10.))) / 301.8 +
|
||||||
|
log (1 + 0.646 * pow (g, 1.175)) / 5.3;
|
||||||
|
Theta = 1.729 + 1.175 * log (1 + 0.627 / (g + 0.327 * pow (g, 2.17)));
|
||||||
|
Po = Pe - Theta / Psi * exp (Beta * pow (u, -n) * log (u));
|
||||||
|
|
||||||
|
// further modifying equations
|
||||||
|
r = 1 + 0.15 * (1 - exp (1 - sqr (er - 1) / 8.2) / (1 + pow (g, -6.)));
|
||||||
|
fo1 = 1 - exp (-0.179 * pow (g, 0.15) -
|
||||||
|
0.328 * pow (g, r) / log (M_E + pow (g / 7, 2.8)));
|
||||||
|
q = exp (-1.366 - g);
|
||||||
|
p = exp (-0.745 * pow (g, 0.295)) / cosh (pow (g, 0.68));
|
||||||
|
fo = fo1 * exp (p * log (u) + q * sin (M_PI * log10 (u)));
|
||||||
|
|
||||||
|
Mu = g * exp (-g) + u * (20 + sqr (g)) / (10 + sqr (g));
|
||||||
|
Hammerstad_ab (Mu, er, &a, &b);
|
||||||
|
Fe = pow (1 + 10 / Mu, -a * b);
|
||||||
|
Hammerstad_ab (u, er, &a, &b);
|
||||||
|
Fo = fo * pow (1 + 10 / u, -a * b);
|
||||||
|
|
||||||
|
// finally compute effective dielectric constants and impedances
|
||||||
|
*ErEffe = (er + 1) / 2 + (er - 1) / 2 * Fe;
|
||||||
|
*ErEffo = (er + 1) / 2 + (er - 1) / 2 * Fo;
|
||||||
|
|
||||||
|
Hammerstad_er (u, er, a, b, &ErEff); // single microstrip
|
||||||
|
|
||||||
|
// first variant
|
||||||
|
Zl1 = Z0 / (u + 1.98 * pow (u, 0.172));
|
||||||
|
Zl1 /= sqrt (ErEff);
|
||||||
|
|
||||||
|
// second variant
|
||||||
|
Hammerstad_zl (u, &Zl1);
|
||||||
|
Zl1 /= sqrt (ErEff);
|
||||||
|
|
||||||
|
*Zle = Zl1 / (1 - Zl1 * Pe / Z0);
|
||||||
|
*Zlo = Zl1 / (1 - Zl1 * Po / Z0);
|
||||||
|
}
|
||||||
|
// KIRSCHNING and JANSEN
|
||||||
|
else if (SModel == KIRSCHING) {
|
||||||
|
double a, b, ae, be, ao, bo, v, co, d, ErEff, Zl1;
|
||||||
|
double q1, q2, q3, q4, q5, q6, q7, q8, q9, q10;
|
||||||
|
|
||||||
|
// consider effect of finite strip thickness (JANSEN only)
|
||||||
|
double ue = u;
|
||||||
|
double uo = u;
|
||||||
|
if (t != 0 && s > 10 * (2 * t)) {
|
||||||
|
double dW = 0;
|
||||||
|
// SCHNEIDER, referred by JANSEN
|
||||||
|
if (u >= M_1_PI / 2 && M_1_PI / 2 > 2 * t / h)
|
||||||
|
dW = t * (1 + log (2 * h / t)) / M_PI;
|
||||||
|
else if (W > 2 * t)
|
||||||
|
dW = t * (1 + log (4 * M_PI * W / t)) / M_PI;
|
||||||
|
// JANSEN
|
||||||
|
double dt = 2 * t * h / s / er;
|
||||||
|
double We = W + dW * (1 - 0.5 * exp (-0.69 * dW / dt));
|
||||||
|
double Wo = We + dt;
|
||||||
|
ue = We / h;
|
||||||
|
uo = Wo / h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// even relative dielectric constant
|
||||||
|
v = ue * (20 + sqr (g)) / (10 + sqr (g)) + g * exp (-g);
|
||||||
|
Hammerstad_ab (v, er, &ae, &be);
|
||||||
|
Hammerstad_er (v, er, ae, be, ErEffe);
|
||||||
|
|
||||||
|
// odd relative dielectric constant
|
||||||
|
Hammerstad_ab (uo, er, &a, &b);
|
||||||
|
Hammerstad_er (uo, er, a, b, &ErEff);
|
||||||
|
d = 0.593 + 0.694 * exp (-0.562 * uo);
|
||||||
|
bo = 0.747 * er / (0.15 + er);
|
||||||
|
co = bo - (bo - 0.207) * exp (-0.414 * uo);
|
||||||
|
ao = 0.7287 * (ErEff - (er + 1) / 2) * (1 - exp (-0.179 * uo));
|
||||||
|
*ErEffo = ((er + 1) / 2 + ao - ErEff) * exp (-co * pow (g, d)) + ErEff;
|
||||||
|
|
||||||
|
// characteristic impedance of single line
|
||||||
|
Hammerstad_zl (u, &Zl1);
|
||||||
|
Zl1 /= sqrt (ErEff);
|
||||||
|
|
||||||
|
// even characteristic impedance
|
||||||
|
q1 = 0.8695 * pow (ue, 0.194);
|
||||||
|
q2 = 1 + 0.7519 * g + 0.189 * pow (g, 2.31);
|
||||||
|
q3 = 0.1975 + pow (16.6 + pow (8.4 / g, 6.), -0.387) +
|
||||||
|
log (pow (g, 10.) / (1 + pow (g / 3.4, 10.))) / 241;
|
||||||
|
q4 = q1 / q2 * 2 /
|
||||||
|
(exp (-g) * pow (ue, q3) + (2 - exp (-g)) * pow (ue, -q3));
|
||||||
|
*Zle = sqrt (ErEff / *ErEffe) * Zl1 / (1 - Zl1 * sqrt (ErEff) * q4 / Z0);
|
||||||
|
|
||||||
|
// odd characteristic impedance
|
||||||
|
q5 = 1.794 + 1.14 * log (1 + 0.638 / (g + 0.517 * pow (g, 2.43)));
|
||||||
|
q6 = 0.2305 + log (pow (g, 10.) / (1 + pow (g / 5.8, 10.))) / 281.3 +
|
||||||
|
log (1 + 0.598 * pow (g, 1.154)) / 5.1;
|
||||||
|
q7 = (10 + 190 * sqr (g)) / (1 + 82.3 * cubic (g));
|
||||||
|
q8 = exp (-6.5 - 0.95 * log (g) - pow (g / 0.15, 5.));
|
||||||
|
q9 = log (q7) * (q8 + 1 / 16.5);
|
||||||
|
q10 = (q2 * q4 - q5 * exp (log (uo) * q6 * pow (uo, -q9))) / q2;
|
||||||
|
*Zlo = sqrt (ErEff / *ErEffo) * Zl1 / (1 - Zl1 * sqrt (ErEff) * q10 / Z0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function computes the dispersion effects on the dielectric
|
||||||
|
constants and characteristic impedances for the even and odd mode
|
||||||
|
of parallel coupled microstrip lines. */
|
||||||
|
static void analyseDispersion (double W, double h, double s,
|
||||||
|
double t, double er, double Zle,
|
||||||
|
double Zlo, double ErEffe,
|
||||||
|
double ErEffo, double frequency,
|
||||||
|
int DModel, double *ZleFreq,
|
||||||
|
double *ZloFreq,
|
||||||
|
double *ErEffeFreq,
|
||||||
|
double *ErEffoFreq) {
|
||||||
|
|
||||||
|
// initialize default return values
|
||||||
|
*ZleFreq = Zle;
|
||||||
|
*ErEffeFreq = ErEffe;
|
||||||
|
*ZloFreq = Zlo;
|
||||||
|
*ErEffoFreq = ErEffo;
|
||||||
|
|
||||||
|
// normalized width and gap
|
||||||
|
double u = W / h;
|
||||||
|
double g = s / h;
|
||||||
|
double ue, uo;
|
||||||
|
double B, dW, dt;
|
||||||
|
|
||||||
|
// compute u_odd, u_even
|
||||||
|
if (t > 0.0) {
|
||||||
|
if (u < 0.1592) {
|
||||||
|
B = 2 * M_PI * W;
|
||||||
|
} else {
|
||||||
|
B = h;
|
||||||
|
}
|
||||||
|
dW = t * (1.0 + log(2 * B / t)) / M_PI;
|
||||||
|
dt = t / (er * g);
|
||||||
|
ue = (W + dW * (1.0 - 0.5 * exp( -0.69 * dW / dt ))) / h;
|
||||||
|
uo = ue + dt / h;
|
||||||
|
} else {
|
||||||
|
ue = u;
|
||||||
|
uo = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GETSINGER
|
||||||
|
if (DModel == GETSINGER) {
|
||||||
|
// even mode dispersion
|
||||||
|
Getsinger_disp (h, er, ErEffe, Zle / 2,
|
||||||
|
frequency, ErEffeFreq, ZleFreq);
|
||||||
|
*ZleFreq *= 2;
|
||||||
|
// odd mode dispersion
|
||||||
|
Getsinger_disp (h, er, ErEffo, Zlo * 2,
|
||||||
|
frequency, ErEffoFreq, ZloFreq);
|
||||||
|
*ZloFreq /= 2;
|
||||||
|
}
|
||||||
|
// KIRSCHNING and JANSEN
|
||||||
|
else if (DModel == DISP_KIRSCHING) {
|
||||||
|
double p1, p2, p3, p4, p5, p6, p7, Fe;
|
||||||
|
double fn = frequency * h * 1e-6;
|
||||||
|
|
||||||
|
// even relative dielectric constant dispersion
|
||||||
|
p1 = 0.27488 * (0.6315 + 0.525 / pow (1 + 0.0157 * fn, 20.)) * ue -
|
||||||
|
0.065683 * exp (-8.7513 * ue);
|
||||||
|
p2 = 0.33622 * (1 - exp (-0.03442 * er));
|
||||||
|
p3 = 0.0363 * exp (-4.6 * ue) * (1 - exp (- pow (fn / 38.7, 4.97)));
|
||||||
|
p4 = 1 + 2.751 * (1 - exp (- pow (er / 15.916, 8.)));
|
||||||
|
p5 = 0.334 * exp (-3.3 * cubic (er / 15)) + 0.746;
|
||||||
|
p6 = p5 * exp (- pow (fn / 18, 0.368));
|
||||||
|
p7 = 1 + 4.069 * p6 * pow (g, 0.479) *
|
||||||
|
exp (-1.347 * pow (g, 0.595) - 0.17 * pow (g, 2.5));
|
||||||
|
Fe = p1 * p2 * pow ((p3 * p4 + 0.1844 * p7) * fn, 1.5763);
|
||||||
|
*ErEffeFreq = er - (er - ErEffe) / (1 + Fe);
|
||||||
|
|
||||||
|
// odd relative dielectric constant dispersion
|
||||||
|
double p8, p9, p10, p11, p12, p13, p14, p15, Fo;
|
||||||
|
p1 = 0.27488 * (0.6315 + 0.525 / pow (1 + 0.0157 * fn, 20.)) * uo -
|
||||||
|
0.065683 * exp (-8.7513 * uo);
|
||||||
|
p3 = 0.0363 * exp (-4.6 * uo) * (1 - exp (- pow (fn / 38.7, 4.97)));
|
||||||
|
p8 = 0.7168 * (1 + 1.076 / (1 + 0.0576 * (er - 1)));
|
||||||
|
p9 = p8 - 0.7913 * (1 - exp (- pow (fn / 20, 1.424))) *
|
||||||
|
atan (2.481 * pow (er / 8, 0.946));
|
||||||
|
p10 = 0.242 * pow (er - 1, 0.55);
|
||||||
|
p11 = 0.6366 * (exp (-0.3401 * fn) - 1) *
|
||||||
|
atan (1.263 * pow (uo / 3, 1.629));
|
||||||
|
p12 = p9 + (1 - p9) / (1 + 1.183 * pow (uo, 1.376));
|
||||||
|
p13 = 1.695 * p10 / (0.414 + 1.605 * p10);
|
||||||
|
p14 = 0.8928 + 0.1072 * (1 - exp (-0.42 * pow (fn / 20, 3.215)));
|
||||||
|
p15 = fabs (1 - 0.8928 * (1 + p11) *
|
||||||
|
exp (-p13 * pow (g, 1.092)) * p12 / p14);
|
||||||
|
Fo = p1 * p2 * pow ((p3 * p4 + 0.1844) * fn * p15, 1.5763);
|
||||||
|
*ErEffoFreq = er - (er - ErEffo) / (1 + Fo);
|
||||||
|
|
||||||
|
// dispersion of even characteristic impedance
|
||||||
|
double t, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21;
|
||||||
|
q11 = 0.893 * (1 - 0.3 / (1 + 0.7 * (er - 1)));
|
||||||
|
t = pow (fn / 20, 4.91);
|
||||||
|
q12 = 2.121 * t / (1 + q11 * t) * exp (-2.87 * g) * pow (g, 0.902);
|
||||||
|
q13 = 1 + 0.038 * pow (er / 8, 5.1);
|
||||||
|
t = quadr (er / 15);
|
||||||
|
q14 = 1 + 1.203 * t / (1 + t);
|
||||||
|
q15 = 1.887 * exp (-1.5 * pow (g, 0.84)) * pow (g, q14) /
|
||||||
|
(1 + 0.41 * pow (fn / 15, 3.) *
|
||||||
|
pow (u, 2 / q13) / (0.125 + pow (u, 1.626 / q13)));
|
||||||
|
q16 = q15 * (1 + 9 / (1 + 0.403 * sqr (er - 1)));
|
||||||
|
q17 = 0.394 * (1 - exp (-1.47 * pow (u / 7, 0.672))) *
|
||||||
|
(1 - exp (-4.25 * pow (fn / 20, 1.87)));
|
||||||
|
q18 = 0.61 * (1 - exp (-2.31 * pow (u / 8, 1.593))) /
|
||||||
|
(1 + 6.544 * pow (g, 4.17));
|
||||||
|
q19 = 0.21 * quadr (g) / (1 + 0.18 * pow (g, 4.9)) / (1 + 0.1 * sqr (u)) /
|
||||||
|
(1 + pow (fn / 24, 3.));
|
||||||
|
q20 = q19 * (0.09 + 1 / (1 + 0.1 * pow (er - 1, 2.7)));
|
||||||
|
t = pow (u, 2.5);
|
||||||
|
q21 = fabs (1 - 42.54 * pow (g, 0.133) * exp (-0.812 * g) * t /
|
||||||
|
(1 + 0.033 * t));
|
||||||
|
|
||||||
|
double re, qe, pe, de, Ce, q0, ZlFreq, ErEffFreq;
|
||||||
|
Kirschning_er (u, fn, er, ErEffe, &ErEffFreq);
|
||||||
|
Kirschning_zl (u, fn, er, ErEffe, ErEffFreq, Zle, &q0, &ZlFreq);
|
||||||
|
re = pow (fn / 28.843, 12.);
|
||||||
|
qe = 0.016 + pow (0.0514 * er * q21, 4.524);
|
||||||
|
pe = 4.766 * exp (-3.228 * pow (u, 0.641));
|
||||||
|
t = pow (er - 1, 6.);
|
||||||
|
de = 5.086 * qe * re / (0.3838 + 0.386 * qe) *
|
||||||
|
exp (-22.2 * pow (u, 1.92)) / (1 + 1.2992 * re) * t / (1 + 10 * t);
|
||||||
|
Ce = 1 + 1.275 * (1 - exp (-0.004625 * pe * pow (er, 1.674) *
|
||||||
|
pow (fn / 18.365, 2.745))) - q12 + q16 - q17 + q18 + q20;
|
||||||
|
*ZleFreq = Zle * pow ((0.9408 * pow (ErEffFreq, Ce) - 0.9603) /
|
||||||
|
((0.9408 - de) * pow (ErEffe, Ce) - 0.9603), q0);
|
||||||
|
|
||||||
|
// dispersion of odd characteristic impedance
|
||||||
|
double q22, q23, q24, q25, q26, q27, q28, q29;
|
||||||
|
Kirschning_er (u, fn, er, ErEffo, &ErEffFreq);
|
||||||
|
Kirschning_zl (u, fn, er, ErEffo, ErEffFreq, Zlo, &q0, &ZlFreq);
|
||||||
|
q29 = 15.16 / (1 + 0.196 * sqr (er - 1));
|
||||||
|
t = sqr (er - 1);
|
||||||
|
q25 = 0.3 * sqr (fn) / (10 + sqr (fn)) * (1 + 2.333 * t / (5 + t));
|
||||||
|
t = pow ((er - 1) / 13, 12.);
|
||||||
|
q26 = 30 - 22.2 * t / (1 + 3 * t) - q29;
|
||||||
|
t = pow (er - 1, 1.5);
|
||||||
|
q27 = 0.4 * pow (g, 0.84) * (1 + 2.5 * t / (5 + t));
|
||||||
|
t = pow (er - 1, 3.);
|
||||||
|
q28 = 0.149 * t / (94.5 + 0.038 * t);
|
||||||
|
q22 = 0.925 * pow (fn / q26, 1.536) / (1 + 0.3 * pow (fn / 30, 1.536));
|
||||||
|
q23 = 1 + 0.005 * fn * q27 / (1 + 0.812 * pow (fn / 15, 1.9)) /
|
||||||
|
(1 + 0.025 * sqr (u));
|
||||||
|
t = pow (u, 0.894);
|
||||||
|
q24 = 2.506 * q28 * t / (3.575 + t) *
|
||||||
|
pow ((1 + 1.3 * u) * fn / 99.25, 4.29);
|
||||||
|
*ZloFreq = ZlFreq + (Zlo * pow (*ErEffoFreq / ErEffo, q22) - ZlFreq * q23) /
|
||||||
|
(1 + q24 + pow (0.46 * g, 2.2) * q25);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cm_cpmline (ARGS)
|
||||||
|
{
|
||||||
|
Complex_t z11, z12, z13, z14;
|
||||||
|
|
||||||
|
/* how to get properties of this component, e.g. L, W */
|
||||||
|
double W = PARAM(w);
|
||||||
|
double l = PARAM(l);
|
||||||
|
double s = PARAM(s);
|
||||||
|
int SModel = PARAM(model);
|
||||||
|
int DModel = PARAM(disp);
|
||||||
|
|
||||||
|
/* how to get properties of the substrate, e.g. Er, H */
|
||||||
|
double er = PARAM(er);
|
||||||
|
double h = PARAM(h);
|
||||||
|
double t = PARAM(t);
|
||||||
|
double tand = PARAM(tand);
|
||||||
|
double rho = PARAM(rho);
|
||||||
|
double D = PARAM(d);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Compute the output */
|
||||||
|
if(ANALYSIS == DC) {
|
||||||
|
calcPropagation(W,s,er,h,t,tand,rho,D,SModel,DModel,0);
|
||||||
|
|
||||||
|
double V1 = INPUT(p1s);
|
||||||
|
double V2 = INPUT(p2s);
|
||||||
|
double V3 = INPUT(p3s);
|
||||||
|
double V4 = INPUT(p4s);
|
||||||
|
double I1 = INPUT(p1);
|
||||||
|
double I2 = INPUT(p2);
|
||||||
|
double I3 = INPUT(p3);
|
||||||
|
double I4 = INPUT(p4);
|
||||||
|
|
||||||
|
double z = sqrt(ze*zo);
|
||||||
|
|
||||||
|
double V2out = V1 + z*I1;
|
||||||
|
double V1out = V2 + z*I2;
|
||||||
|
OUTPUT(p1) = V1out + I1*z;
|
||||||
|
OUTPUT(p2) = V2out + I2*z;
|
||||||
|
|
||||||
|
double V3out = V4 + z*I4;
|
||||||
|
double V4out = V3 + z*I3;
|
||||||
|
OUTPUT(p3) = V3out + I3*z;
|
||||||
|
OUTPUT(p4) = V4out + I4*z;
|
||||||
|
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == AC) {
|
||||||
|
double o = RAD_FREQ;
|
||||||
|
calcPropagation(W,s,er,h,t,tand,rho,D,SModel,DModel, o/(2*M_PI));
|
||||||
|
double complex _Z11, _Z12, _Z13, _Z14;
|
||||||
|
double complex ge = ae + I*be;
|
||||||
|
double complex go = ao + I*bo;
|
||||||
|
|
||||||
|
_Z11 = zo / (2*ctanh(go*l)) + ze / (2*ctanh(ge*l));
|
||||||
|
_Z12 = zo / (2*csinh(go*l)) + ze / (2*csinh(ge*l));
|
||||||
|
_Z13 = ze / (2*csinh(ge*l)) - zo / (2*csinh(go*l));
|
||||||
|
_Z14 = ze / (2*ctanh(ge*l)) - zo / (2*ctanh(go*l));
|
||||||
|
|
||||||
|
copy_complex(_Z11,&z11);
|
||||||
|
copy_complex(_Z12,&z12);
|
||||||
|
copy_complex(_Z13,&z13);
|
||||||
|
copy_complex(_Z14,&z14);
|
||||||
|
|
||||||
|
AC_GAIN(p1,p1) = z11; AC_GAIN(p2,p2) = z11;
|
||||||
|
AC_GAIN(p3,p3) = z11; AC_GAIN(p4,p4) = z11;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p2) = z12; AC_GAIN(p2,p1) = z12;
|
||||||
|
AC_GAIN(p3,p4) = z12; AC_GAIN(p4,p3) = z12;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p3) = z13; AC_GAIN(p3,p1) = z13;
|
||||||
|
AC_GAIN(p2,p4) = z13; AC_GAIN(p4,p2) = z13;
|
||||||
|
|
||||||
|
AC_GAIN(p1,p4) = z14; AC_GAIN(p4,p1) = z14;
|
||||||
|
AC_GAIN(p2,p3) = z14; AC_GAIN(p3,p2) = z14;
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == TRANSIENT) {
|
||||||
|
calcPropagation(W,s,er,h,t,tand,rho,D,SModel,DModel,0);
|
||||||
|
double t = TIME;
|
||||||
|
double Vp[PORT_NUM];
|
||||||
|
double Ip[PORT_NUM];
|
||||||
|
double Vnew[PORT_NUM];
|
||||||
|
Vp[0] = INPUT(p1s);
|
||||||
|
Vp[1] = INPUT(p2s);
|
||||||
|
Vp[2] = INPUT(p3s);
|
||||||
|
Vp[3] = INPUT(p4s);
|
||||||
|
Ip[0] = INPUT(p1);
|
||||||
|
Ip[1] = INPUT(p2);
|
||||||
|
Ip[2] = INPUT(p3);
|
||||||
|
Ip[3] = INPUT(p4);
|
||||||
|
double delay = l/(C0);
|
||||||
|
append_cpline_state(&state, t, Vp, Ip, 1.2*delay);
|
||||||
|
if (t > delay) {
|
||||||
|
cpline_state_t *pp = find_cpline_state(state, t - delay);
|
||||||
|
if (pp != NULL) {
|
||||||
|
|
||||||
|
double J1e = 0.5*(Ip[3] + Ip[0]);
|
||||||
|
double J1o = 0.5*(Ip[0] - Ip[3]);
|
||||||
|
double J2e = 0.5*(Ip[1] + Ip[2]);
|
||||||
|
double J2o = 0.5*(Ip[1] - Ip[2]);
|
||||||
|
|
||||||
|
|
||||||
|
double J1et = 0.5*(pp->Ip[3] + pp->Ip[0]);
|
||||||
|
double J1ot = 0.5*(pp->Ip[0] - pp->Ip[3]);
|
||||||
|
double J2et = 0.5*(pp->Ip[1] + pp->Ip[2]);
|
||||||
|
double J2ot = 0.5*(pp->Ip[1] - pp->Ip[2]);
|
||||||
|
|
||||||
|
|
||||||
|
double V1et = 0.5*(pp->Vp[3] + pp->Vp[0]);
|
||||||
|
double V1ot = 0.5*(pp->Vp[0] - pp->Vp[3]);
|
||||||
|
double V2et = 0.5*(pp->Vp[1] + pp->Vp[2]);
|
||||||
|
double V2ot = 0.5*(pp->Vp[1] - pp->Vp[2]);
|
||||||
|
|
||||||
|
double V1e = ze*J1e + V2et + ze*J2et;
|
||||||
|
double V1o = zo*J1o + V2ot + zo*J2ot;
|
||||||
|
double V2e = ze*J2e + V1et + ze*J1et;
|
||||||
|
double V2o = zo*J2o + V1ot + zo*J1ot;
|
||||||
|
|
||||||
|
double V1 = V1o + V1e;
|
||||||
|
double V2 = V2o + V2e;
|
||||||
|
double V3 = V2e - V2o;
|
||||||
|
double V4 = V1e - V1o;
|
||||||
|
|
||||||
|
OUTPUT(p1) = V1;
|
||||||
|
OUTPUT(p2) = V2;
|
||||||
|
OUTPUT(p3) = V3;
|
||||||
|
OUTPUT(p4) = V4;
|
||||||
|
}
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
} else {
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE ifspec.ifs
|
||||||
|
|
||||||
|
(c) vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
=========================================================================== */
|
||||||
|
|
||||||
|
/* Ports connection
|
||||||
|
4 --||||||-- 3
|
||||||
|
|
||||||
|
1 --||||||-- 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
NAME_TABLE:
|
||||||
|
|
||||||
|
Spice_Model_Name: cpmlin
|
||||||
|
C_Function_Name: cm_cpmline
|
||||||
|
Description: "Generic transmission line"
|
||||||
|
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p1
|
||||||
|
Description: "Terminals Line1"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p2
|
||||||
|
Description: "Terminals Line1"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p3
|
||||||
|
Description: "Terminals Line2"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p4
|
||||||
|
Description: "Terminals Line2"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p1s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p2s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p3s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: p4s
|
||||||
|
Description: "Sensing terminals line 1"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: l
|
||||||
|
Description: "length"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: w
|
||||||
|
Description: "width"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-3
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: s
|
||||||
|
Description: "gap"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-3
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: model
|
||||||
|
Description: "Model type"
|
||||||
|
Data_Type: int
|
||||||
|
Default_Value: 0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: disp
|
||||||
|
Description: "Dispersion type"
|
||||||
|
Data_Type: int
|
||||||
|
Default_Value: 0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: er
|
||||||
|
Description: "Substrate dielectric permittivity"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 9.8
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: h
|
||||||
|
Description: "Substrate thickness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-3
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: t
|
||||||
|
Description: "Metal strip thickness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 35e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: tand
|
||||||
|
Description: "Substrate dielectric loss"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 2e-4
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: rho
|
||||||
|
Description: "Metal resistance"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.022e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: d
|
||||||
|
Description: "RMS Substrate roughness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.15e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE cfunc.mod
|
||||||
|
|
||||||
|
(c) Vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <complex.h>
|
||||||
|
|
||||||
|
#include "tline_common.h"
|
||||||
|
|
||||||
|
#include "msline_common.h"
|
||||||
|
|
||||||
|
static tline_state_t *sim_points = NULL;
|
||||||
|
|
||||||
|
static double zl, alpha, beta, ereff;
|
||||||
|
|
||||||
|
static void calcPropagation (double W, int SModel, int DModel,
|
||||||
|
double er, double h, double t, double tand, double rho, double D,
|
||||||
|
double frequency) {
|
||||||
|
|
||||||
|
/* local variables */
|
||||||
|
double ac, ad;
|
||||||
|
double ZlEff, ErEff, WEff, ZlEffFreq, ErEffFreq;
|
||||||
|
|
||||||
|
// quasi-static effective dielectric constant of substrate + line and
|
||||||
|
// the impedance of the microstrip line
|
||||||
|
mslineAnalyseQuasiStatic (W, h, t, er, SModel, &ZlEff, &ErEff, &WEff);
|
||||||
|
|
||||||
|
// analyse dispersion of Zl and Er (use WEff here?)
|
||||||
|
mslineAnalyseDispersion (W, h, er, ZlEff, ErEff, frequency, DModel,
|
||||||
|
&ZlEffFreq, &ErEffFreq);
|
||||||
|
|
||||||
|
// analyse losses of line
|
||||||
|
analyseLoss (W, t, er, rho, D, tand, ZlEff, ZlEff, ErEff,
|
||||||
|
frequency, HAMMERSTAD, &ac, &ad);
|
||||||
|
|
||||||
|
// calculate propagation constants and reference impedance
|
||||||
|
zl = ZlEffFreq;
|
||||||
|
ereff = ErEffFreq;
|
||||||
|
alpha = ac + ad;
|
||||||
|
beta = sqrt (ErEffFreq) * 2 * M_PI * frequency / C0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cm_mlin (ARGS)
|
||||||
|
{
|
||||||
|
Complex_t z11, z21;
|
||||||
|
|
||||||
|
|
||||||
|
/* how to get properties of this component, e.g. L, W */
|
||||||
|
double W = PARAM(w);
|
||||||
|
double l = PARAM(l);
|
||||||
|
int SModel = PARAM(model);
|
||||||
|
int DModel = PARAM(disp);
|
||||||
|
int TModel = PARAM(tranmodel);
|
||||||
|
|
||||||
|
/* how to get properties of the substrate, e.g. Er, H */
|
||||||
|
double er = PARAM(er);
|
||||||
|
double h = PARAM(h);
|
||||||
|
double t = PARAM(t);
|
||||||
|
double tand = PARAM(tand);
|
||||||
|
double rho = PARAM(rho);
|
||||||
|
double D = PARAM(d);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Initialize/access instance specific storage for capacitor voltage */
|
||||||
|
if(INIT) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the output */
|
||||||
|
if(ANALYSIS == DC) {
|
||||||
|
|
||||||
|
calcPropagation(W,SModel,DModel,er,h,t,tand,rho,D,0);
|
||||||
|
double V1 = INPUT(V1sens);
|
||||||
|
double V2 = INPUT(V2sens);
|
||||||
|
double I1 = INPUT(port1);
|
||||||
|
double I2 = INPUT(port2);
|
||||||
|
double V2out = V1 + zl*I1;
|
||||||
|
double V1out = V2 + zl*I2;
|
||||||
|
OUTPUT(port1) = V1out + I1*zl;
|
||||||
|
OUTPUT(port2) = V2out + I2*zl;
|
||||||
|
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == AC) {
|
||||||
|
double frequency = RAD_FREQ/(2.0*M_PI);
|
||||||
|
calcPropagation(W,SModel,DModel,er,h,t,tand,rho,D,frequency);
|
||||||
|
|
||||||
|
double complex g = alpha + beta*I;
|
||||||
|
double complex _Z11 = zl / ctanh(g*l);
|
||||||
|
double complex _Z21 = zl / csinh(g*l);
|
||||||
|
|
||||||
|
z11.real = creal(_Z11); z11.imag = cimag(_Z11);
|
||||||
|
z21.real = creal(_Z21); z21.imag = cimag(_Z21);
|
||||||
|
|
||||||
|
AC_GAIN(port1,port1) = z11; AC_GAIN(port2,port2) = z11;
|
||||||
|
AC_GAIN(port1,port2) = z21; AC_GAIN(port2,port1) = z21;
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == TRANSIENT) {
|
||||||
|
calcPropagation(W,SModel,DModel,er,h,t,tand,rho,D,0);
|
||||||
|
double t = TIME;
|
||||||
|
double V1 = INPUT(V1sens);
|
||||||
|
double V2 = INPUT(V2sens);
|
||||||
|
double I1 = INPUT(port1);
|
||||||
|
double I2 = INPUT(port2);
|
||||||
|
double delay = l/(C0) * sqrt(ereff);
|
||||||
|
if (TModel == TRAN_FULL) {
|
||||||
|
append_state(&sim_points, t, V1, V2, I1, I2, 1.2*delay);
|
||||||
|
}
|
||||||
|
if (t > delay && TModel == TRAN_FULL) {
|
||||||
|
tline_state_t *pp = get_state(sim_points, t - delay);
|
||||||
|
if (pp != NULL) {
|
||||||
|
double V2out = pp->V1 + zl*(pp->I1);
|
||||||
|
double V1out = pp->V2 + zl*(pp->I2);
|
||||||
|
OUTPUT(port1) = V1out + I1*zl;
|
||||||
|
OUTPUT(port2) = V2out + I2*zl;
|
||||||
|
}
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
} else {
|
||||||
|
double V2out = V1 + zl*I1;
|
||||||
|
double V1out = V2 + zl*I2;
|
||||||
|
OUTPUT(port1) = V1out + I1*zl;
|
||||||
|
OUTPUT(port2) = V2out + I2*zl;
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE ifspec.ifs
|
||||||
|
|
||||||
|
(c) vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
=========================================================================== */
|
||||||
|
|
||||||
|
NAME_TABLE:
|
||||||
|
|
||||||
|
Spice_Model_Name: mlin
|
||||||
|
C_Function_Name: cm_mlin
|
||||||
|
Description: "Microstrip line"
|
||||||
|
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: port1
|
||||||
|
Description: "Microstrip terminals"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: port2
|
||||||
|
Description: "Microstrip terminals"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: V1sens
|
||||||
|
Description: "Sensing terminals"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: V2sens
|
||||||
|
Description: "Sensisng terminals"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: l
|
||||||
|
Description: "length"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-2
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: w
|
||||||
|
Description: "width"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-3
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: model
|
||||||
|
Description: "Model type"
|
||||||
|
Data_Type: int
|
||||||
|
Default_Value: 0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: disp
|
||||||
|
Description: "Dispersion type"
|
||||||
|
Data_Type: int
|
||||||
|
Default_Value: 0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: er
|
||||||
|
Description: "Substrate dielectric permittivity"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 9.8
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: h
|
||||||
|
Description: "Substrate thickness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1e-3
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: t
|
||||||
|
Description: "Metal strip thickness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 35e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: tand
|
||||||
|
Description: "Substrate dielectric loss"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 2e-4
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: rho
|
||||||
|
Description: "Metal resistance"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.022e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: d
|
||||||
|
Description: "RMS Substrate roughness"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.15e-6
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: tranmodel
|
||||||
|
Description: "RMS Substrate roughness"
|
||||||
|
Data_Type: int
|
||||||
|
Default_Value: 0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
mlin
|
||||||
|
tline
|
||||||
|
cpline
|
||||||
|
cpmlin
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE cfunc.mod
|
||||||
|
|
||||||
|
(c) Vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <complex.h>
|
||||||
|
|
||||||
|
#include "msline_common.h"
|
||||||
|
#include "tline_common.h"
|
||||||
|
|
||||||
|
static tline_state_t *sim_points = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void cm_tline (ARGS)
|
||||||
|
{
|
||||||
|
Complex_t z11, z21;
|
||||||
|
|
||||||
|
|
||||||
|
/* how to get properties of this component, e.g. L, W */
|
||||||
|
double z = PARAM(z);
|
||||||
|
double l = PARAM(l);
|
||||||
|
double a = PARAM(a);
|
||||||
|
|
||||||
|
double alpha = pow(10,0.05*a);
|
||||||
|
alpha = log(alpha)/2.0;
|
||||||
|
|
||||||
|
/* Initialize/access instance specific storage for capacitor voltage */
|
||||||
|
if(INIT) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the output */
|
||||||
|
if(ANALYSIS == DC) {
|
||||||
|
|
||||||
|
double V1 = INPUT(V1sens);
|
||||||
|
double V2 = INPUT(V2sens);
|
||||||
|
double I1 = INPUT(in);
|
||||||
|
double I2 = INPUT(out);
|
||||||
|
double V2out = V1 + z*I1;
|
||||||
|
double V1out = V2 + z*I2;
|
||||||
|
OUTPUT(in) = V1out + I1*z;
|
||||||
|
OUTPUT(out) = V2out + I2*z;
|
||||||
|
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == AC) {
|
||||||
|
double beta = RAD_FREQ/C0;
|
||||||
|
double complex g = alpha + beta*I;
|
||||||
|
double complex _Z11 = z / ctanh(g*l);
|
||||||
|
double complex _Z21 = z / csinh (g*l);
|
||||||
|
|
||||||
|
z11.real = creal(_Z11);
|
||||||
|
z11.imag = cimag(_Z11);
|
||||||
|
z21.real = creal(_Z21);
|
||||||
|
z21.imag = cimag(_Z21);
|
||||||
|
|
||||||
|
|
||||||
|
AC_GAIN(in, in) = z11; AC_GAIN(out,out) = z11;
|
||||||
|
AC_GAIN(in,out) = z21; AC_GAIN(out,in) = z21;
|
||||||
|
}
|
||||||
|
else if(ANALYSIS == TRANSIENT) {
|
||||||
|
double t = TIME;
|
||||||
|
double V1 = INPUT(V1sens);
|
||||||
|
double V2 = INPUT(V2sens);
|
||||||
|
double I1 = INPUT(in);
|
||||||
|
double I2 = INPUT(out);
|
||||||
|
double delay = l/(C0);
|
||||||
|
append_state(&sim_points, t, V1, V2, I1, I2, 1.2*delay);
|
||||||
|
if (t > delay) {
|
||||||
|
tline_state_t *pp = get_state(sim_points, t - delay);
|
||||||
|
if (pp != NULL) {
|
||||||
|
double V2out = pp->V1 + z*(pp->I1);
|
||||||
|
double V1out = pp->V2 + z*(pp->I2);
|
||||||
|
OUTPUT(in) = V1out + I1*z;
|
||||||
|
OUTPUT(out) = V2out + I2*z;
|
||||||
|
}
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
} else {
|
||||||
|
double V2out = V1 + z*I1;
|
||||||
|
double V1out = V2 + z*I2;
|
||||||
|
OUTPUT(in) = V1out + I1*z;
|
||||||
|
OUTPUT(out) = V2out + I2*z;
|
||||||
|
cm_analog_auto_partial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
/* ===========================================================================
|
||||||
|
FILE ifspec.ifs
|
||||||
|
|
||||||
|
(c) vadim Kuznetsov 2025
|
||||||
|
|
||||||
|
=========================================================================== */
|
||||||
|
|
||||||
|
NAME_TABLE:
|
||||||
|
|
||||||
|
Spice_Model_Name: tline
|
||||||
|
C_Function_Name: cm_tline
|
||||||
|
Description: "Generic transmission line"
|
||||||
|
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: in
|
||||||
|
Description: "Terminals"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: out
|
||||||
|
Description: "Terminals"
|
||||||
|
Direction: inout
|
||||||
|
Default_Type: hd
|
||||||
|
Allowed_Types: [hd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: V1sens
|
||||||
|
Description: "Sensing terminals"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
PORT_TABLE:
|
||||||
|
Port_Name: V2sens
|
||||||
|
Description: "Sensisng terminals"
|
||||||
|
Direction: in
|
||||||
|
Default_Type: vd
|
||||||
|
Allowed_Types: [vd]
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: no
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: l
|
||||||
|
Description: "length"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 1.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: z
|
||||||
|
Description: "characteristic impedance"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 50.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
PARAMETER_TABLE:
|
||||||
|
Parameter_Name: a
|
||||||
|
Description: "attenuation per length (dB)"
|
||||||
|
Data_Type: real
|
||||||
|
Default_Value: 0.0
|
||||||
|
Limits: -
|
||||||
|
Vector: no
|
||||||
|
Vector_Bounds: -
|
||||||
|
Null_Allowed: yes
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,337 @@
|
||||||
|
/* msline_common.c
|
||||||
|
* common definitions for microstrip devices
|
||||||
|
* (c) Vadim Kuznetsov 2025
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
#include "tline_common.h"
|
||||||
|
#include "msline_common.h"
|
||||||
|
|
||||||
|
/* This function calculates the quasi-static impedance of a microstrip
|
||||||
|
* line, the value of the effective dielectric constant and the
|
||||||
|
* effective width due to the finite conductor thickness for the given
|
||||||
|
* microstrip line and substrate properties. */
|
||||||
|
void mslineAnalyseQuasiStatic (double W, double h, double t,
|
||||||
|
double er, int Model,
|
||||||
|
double *ZlEff, double *ErEff,
|
||||||
|
double *WEff) {
|
||||||
|
|
||||||
|
double z, e;
|
||||||
|
|
||||||
|
// default values
|
||||||
|
e = er;
|
||||||
|
z = z0;
|
||||||
|
*WEff = W;
|
||||||
|
|
||||||
|
// WHEELER
|
||||||
|
if (Model == WHEELER) {
|
||||||
|
double a, b, c, d, x, dW1, dWr, Wr;
|
||||||
|
|
||||||
|
// compute strip thickness effect
|
||||||
|
if (t != 0) {
|
||||||
|
dW1 = t / M_PI * log (4 * M_E / sqrt (sqr (t / h) +
|
||||||
|
sqr (M_1_PI / (W / t + 1.10))));
|
||||||
|
}
|
||||||
|
else dW1 = 0;
|
||||||
|
dWr = (1 + 1 / er) / 2 * dW1;
|
||||||
|
Wr = W + dWr; *WEff =Wr;
|
||||||
|
|
||||||
|
// compute characteristic impedance
|
||||||
|
if (W / h < 3.3) {
|
||||||
|
c = log (4 * h / Wr + sqrt (sqr (4 * h / Wr) + 2));
|
||||||
|
b = (er - 1) / (er + 1) / 2 * (log (M_PI_2) + log (2 * M_2_PI) / er);
|
||||||
|
z = (c - b) * Z0 / M_PI / sqrt (2 * (er + 1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = 1 + log (M_PI_2) + log (Wr / h / 2 + 0.94);
|
||||||
|
d = M_1_PI / 2 * (1 + log (sqr (M_PI) / 16)) * (er - 1) / sqr (er);
|
||||||
|
x = 2 * M_LN2 / M_PI + Wr / h / 2 + (er + 1) / 2 / M_PI / er * c + d;
|
||||||
|
z = Z0 / 2 / x / sqrt (er);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compute effective dielectric constant
|
||||||
|
if (W / h < 1.3) {
|
||||||
|
a = log (8 * h / Wr) + sqr (Wr / h) / 32;
|
||||||
|
b = (er - 1) / (er + 1) / 2 * (log (M_PI_2) + log (2 * M_2_PI) / er);
|
||||||
|
e = (er + 1) / 2 * sqr (a / (a - b));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a = (er - 1) / 2 / M_PI / er * (log (2.1349 * Wr / h + 4.0137) -
|
||||||
|
0.5169 / er);
|
||||||
|
b = Wr / h / 2 + M_1_PI * log (8.5397 * Wr / h + 16.0547);
|
||||||
|
e = er * sqr ((b - a) / b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SCHNEIDER
|
||||||
|
else if (Model == SCHNEIDER) {
|
||||||
|
|
||||||
|
double dW = 0, u = W / h;
|
||||||
|
|
||||||
|
// consider strip thickness equations
|
||||||
|
if (t != 0 && t < W / 2) {
|
||||||
|
double arg = (u < M_1_PI / 2) ? 2 * M_PI * W / t : h / t;
|
||||||
|
dW = t / M_PI * (1 + log (2 * arg));
|
||||||
|
if (t / dW >= 0.75) dW = 0;
|
||||||
|
}
|
||||||
|
*WEff = W + dW; u = *WEff / h;
|
||||||
|
|
||||||
|
// effective dielectric constant
|
||||||
|
e = (er + 1) / 2 + (er - 1) / 2 / sqrt (1 + 10 / u);
|
||||||
|
|
||||||
|
// characteristic impedance
|
||||||
|
if (u < 1.0) {
|
||||||
|
z = M_1_PI / 2 * log (8 / u + u / 4);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
z = 1 / (u + 2.42 - 0.44 / u + pow ((1. - 1. / u), 6.));
|
||||||
|
}
|
||||||
|
z = Z0 * z / sqrt (e);
|
||||||
|
}
|
||||||
|
// HAMMERSTAD and JENSEN
|
||||||
|
else if (Model == HAMMERSTAD) {
|
||||||
|
double a, b, du1, du, u, ur, u1, zr, z1;
|
||||||
|
|
||||||
|
u = W / h; // normalized width
|
||||||
|
t = t / h; // normalized thickness
|
||||||
|
|
||||||
|
// compute strip thickness effect
|
||||||
|
if (t != 0) {
|
||||||
|
du1 = t / M_PI * log (1 + 4 * M_E / t / sqr (coth (sqrt (6.517 * u))));
|
||||||
|
}
|
||||||
|
else du1 = 0;
|
||||||
|
du = du1 * (1 + sech (sqrt (er - 1))) / 2;
|
||||||
|
u1 = u + du1;
|
||||||
|
ur = u + du;
|
||||||
|
*WEff = ur * h;
|
||||||
|
|
||||||
|
// compute impedances for homogeneous medium
|
||||||
|
Hammerstad_zl (ur, &zr);
|
||||||
|
Hammerstad_zl (u1, &z1);
|
||||||
|
|
||||||
|
// compute effective dielectric constant
|
||||||
|
Hammerstad_ab (ur, er, &a, &b);
|
||||||
|
Hammerstad_er (ur, er, a, b, &e);
|
||||||
|
|
||||||
|
// compute final characteristic impedance and dielectric constant
|
||||||
|
// including strip thickness effects
|
||||||
|
z = zr / sqrt (e);
|
||||||
|
e = e * sqr (z1 / zr);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ZlEff = z;
|
||||||
|
*ErEff = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function calculates the frequency dependent value of the
|
||||||
|
* effective dielectric constant and the microstrip line impedance for
|
||||||
|
* the given frequency. */
|
||||||
|
void mslineAnalyseDispersion (double W, double h, double er,
|
||||||
|
double ZlEff, double ErEff,
|
||||||
|
double frequency, int Model,
|
||||||
|
double* ZlEffFreq,
|
||||||
|
double* ErEffFreq) {
|
||||||
|
|
||||||
|
double e, z;
|
||||||
|
|
||||||
|
// default values
|
||||||
|
z = *ZlEffFreq = ZlEff;
|
||||||
|
e = *ErEffFreq = ErEff;
|
||||||
|
|
||||||
|
// GETSINGER
|
||||||
|
if (Model == GETSINGER) {
|
||||||
|
Getsinger_disp (h, er, ErEff, ZlEff, frequency, &e, &z);
|
||||||
|
}
|
||||||
|
// SCHNEIDER
|
||||||
|
else if (Model == DISP_SCHNEIDER) {
|
||||||
|
double k, f;
|
||||||
|
k = sqrt (ErEff / er);
|
||||||
|
f = 4 * h * frequency / C0 * sqrt (er - 1);
|
||||||
|
f = sqr (f);
|
||||||
|
e = ErEff * sqr ((1 + f) / (1 + k * f));
|
||||||
|
z = ZlEff * sqrt (ErEff / e);
|
||||||
|
}
|
||||||
|
// YAMASHITA
|
||||||
|
else if (Model == YAMASHITA) {
|
||||||
|
double k, f;
|
||||||
|
k = sqrt (er / ErEff);
|
||||||
|
f = 4 * h * frequency / C0 * sqrt (er - 1) *
|
||||||
|
(0.5 + sqr (1 + 2 * log10 (1 + W / h)));
|
||||||
|
e = ErEff * sqr ((1 + k * pow (f, 1.5) / 4) / (1 + pow (f, 1.5) / 4));
|
||||||
|
}
|
||||||
|
// KOBAYASHI
|
||||||
|
else if (Model == KOBAYASHI) {
|
||||||
|
double n, no, nc, fh, fk;
|
||||||
|
fk = C0 * atan (er * sqrt ((ErEff - 1) / (er - ErEff))) /
|
||||||
|
(2 * M_PI * h * sqrt (er - ErEff));
|
||||||
|
fh = fk / (0.75 + (0.75 - 0.332 / pow (er, 1.73)) * W / h);
|
||||||
|
no = 1 + 1 / (1 + sqrt (W / h)) + 0.32 * cubic (1 / (1 + sqrt (W / h)));
|
||||||
|
if (W / h < 0.7) {
|
||||||
|
nc = 1 + 1.4 / (1 + W / h) * (0.15 - 0.235 *
|
||||||
|
exp (-0.45 * frequency / fh));
|
||||||
|
}
|
||||||
|
else nc = 1;
|
||||||
|
n = no * nc < 2.32 ? no * nc : 2.32;
|
||||||
|
e = er - (er - ErEff) / (1 + pow (frequency / fh, n));
|
||||||
|
}
|
||||||
|
// PRAMANICK and BHARTIA
|
||||||
|
else if (Model == PRAMANICK) {
|
||||||
|
double Weff, We, f;
|
||||||
|
f = 2 * MU0 * h * frequency * sqrt (ErEff / er) / ZlEff;
|
||||||
|
e = er - (er - ErEff) / (1 + sqr (f));
|
||||||
|
Weff = Z0 * h / ZlEff / sqrt (ErEff);
|
||||||
|
We = W + (Weff - W) / (1 + sqr (f));
|
||||||
|
z = Z0 * h / We / sqrt (e);
|
||||||
|
}
|
||||||
|
// HAMMERSTAD and JENSEN
|
||||||
|
else if (Model == DISP_HAMMERSTAD) {
|
||||||
|
double f, g;
|
||||||
|
g = sqr (M_PI) / 12 * (er - 1) / ErEff * sqrt (2 * M_PI * ZlEff / Z0);
|
||||||
|
f = 2 * MU0 * h * frequency / ZlEff;
|
||||||
|
e = er - (er - ErEff) / (1 + g * sqr (f));
|
||||||
|
z = ZlEff * sqrt (ErEff / e) * (e - 1) / (ErEff - 1);
|
||||||
|
}
|
||||||
|
// KIRSCHNING and JANSEN
|
||||||
|
else if (Model == DISP_KIRSCHING) {
|
||||||
|
double r17, u = W / h, fn = frequency * h / 1e6;
|
||||||
|
|
||||||
|
// dispersion of dielectric constant
|
||||||
|
Kirschning_er (u, fn, er, ErEff, &e);
|
||||||
|
|
||||||
|
// dispersion of characteristic impedance
|
||||||
|
Kirschning_zl (u, fn, er, ErEff, e, ZlEff, &r17, &z);
|
||||||
|
}
|
||||||
|
|
||||||
|
*ZlEffFreq = z;
|
||||||
|
*ErEffFreq = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Computes the exponent factors a(u) and b(er) used within the
|
||||||
|
* effective relative dielectric constant calculations for single and
|
||||||
|
* coupled microstrip lines by Hammerstad and Jensen. */
|
||||||
|
void Hammerstad_ab (double u, double er, double *a,
|
||||||
|
double *b) {
|
||||||
|
*a = 1 + log ((quadr (u) + sqr (u / 52)) / (quadr (u) + 0.432)) / 49 +
|
||||||
|
log (1 + cubic (u / 18.1)) / 18.7;
|
||||||
|
*b = 0.564 * pow ((er - 0.9) / (er + 3), 0.053);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function computes the effective dielectric constant of a single
|
||||||
|
* microstrip. The equation is used in single and coupled microstrip
|
||||||
|
* calculations. */
|
||||||
|
void Hammerstad_er (double u, double er, double a,
|
||||||
|
double b, double* e) {
|
||||||
|
*e = (er + 1) / 2 + (er - 1) / 2 * pow (1 + 10 / u, -a * b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function computes the characteristic impedance of single
|
||||||
|
* microstrip line based upon the given width-height ratio. The
|
||||||
|
* equation is used in single and coupled microstrip calculations as
|
||||||
|
* well. */
|
||||||
|
void Hammerstad_zl (double u, double *zl) {
|
||||||
|
double fu = 6 + (2 * M_PI - 6) * exp (- pow (30.666 / u, 0.7528));
|
||||||
|
*zl = Z0 / 2 / M_PI * log (fu / u + sqrt (1 + sqr (2 / u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculates dispersion effects for effective dielectric constant and
|
||||||
|
* characteristic impedance as defined by Getsinger (for single and
|
||||||
|
* coupled microstrips). */
|
||||||
|
void Getsinger_disp (double h, double er, double ErEff,
|
||||||
|
double ZlEff, double frequency,
|
||||||
|
double *e, double *z) {
|
||||||
|
double g, f, d;
|
||||||
|
g = 0.6 + 0.009 * ZlEff;
|
||||||
|
f = frequency * 2 * MU0 * h / ZlEff;
|
||||||
|
*e = er - (er - ErEff) / (1 + g * sqr (f));
|
||||||
|
d = (er - *e) * (*e - ErEff) / *e / (er - ErEff);
|
||||||
|
*z = ZlEff * sqrt (*e / ErEff) / (1 + d); // group delay model
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function computes the dispersion of the effective dielectric
|
||||||
|
* constant of a single microstrip line. It is defined in a separate
|
||||||
|
* function because it is used within the coupled microstrip lines as
|
||||||
|
* well. */
|
||||||
|
void Kirschning_er (double u, double fn, double er,
|
||||||
|
double ErEff, double* ErEffFreq) {
|
||||||
|
double p, p1, p2, p3, p4;
|
||||||
|
p1 = 0.27488 + (0.6315 + 0.525 / pow (1. + 0.0157 * fn, 20.)) * u -
|
||||||
|
0.065683 * exp (-8.7513 * u);
|
||||||
|
p2 = 0.33622 * (1 - exp (-0.03442 * er));
|
||||||
|
p3 = 0.0363 * exp (-4.6 * u) * (1 - exp (- pow (fn / 38.7, 4.97)));
|
||||||
|
p4 = 1 + 2.751 * (1 - exp (- pow (er / 15.916, 8.)));
|
||||||
|
p = p1 * p2 * pow ((0.1844 + p3 * p4) * fn, 1.5763);
|
||||||
|
*ErEffFreq = er - (er - ErEff) / (1 + p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computes dispersion effects of characteristic impedance of a single
|
||||||
|
* microstrip line according to Kirschning and Jansen. Also used in
|
||||||
|
* coupled microstrip lines calculations. */
|
||||||
|
void Kirschning_zl (double u, double fn, double er,
|
||||||
|
double ErEff, double ErEffFreq,
|
||||||
|
double ZlEff, double* r17,
|
||||||
|
double* ZlEffFreq) {
|
||||||
|
double r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
|
||||||
|
double r11, r12, r13, r14, r15, r16;
|
||||||
|
r1 = 0.03891 * pow (er, 1.4);
|
||||||
|
r2 = 0.267 * pow (u, 7.);
|
||||||
|
r3 = 4.766 * exp (-3.228 * pow (u, 0.641));
|
||||||
|
r4 = 0.016 + pow (0.0514 * er, 4.524);
|
||||||
|
r5 = pow (fn / 28.843, 12.);
|
||||||
|
r6 = 22.20 * pow (u, 1.92);
|
||||||
|
r7 = 1.206 - 0.3144 * exp (-r1) * (1 - exp (-r2));
|
||||||
|
r8 = 1 + 1.275 * (1 - exp (-0.004625 * r3 *
|
||||||
|
pow (er, 1.674) * pow (fn / 18.365, 2.745)));
|
||||||
|
r9 = 5.086 * r4 * r5 / (0.3838 + 0.386 * r4) *
|
||||||
|
exp (-r6) / (1 + 1.2992 * r5) *
|
||||||
|
pow (er - 1., 6.) / (1 + 10 * pow (er - 1., 6.));
|
||||||
|
r10 = 0.00044 * pow (er, 2.136) + 0.0184;
|
||||||
|
r11 = pow (fn / 19.47, 6.) / (1 + 0.0962 * pow (fn / 19.47, 6.));
|
||||||
|
r12 = 1 / (1 + 0.00245 * sqr (u));
|
||||||
|
r13 = 0.9408 * pow (ErEffFreq, r8) - 0.9603;
|
||||||
|
r14 = (0.9408 - r9) * pow (ErEff, r8) - 0.9603;
|
||||||
|
r15 = 0.707 * r10 * pow (fn / 12.3, 1.097);
|
||||||
|
r16 = 1 + 0.0503 * sqr (er) * r11 * (1 - exp (- pow (u / 15., 6.)));
|
||||||
|
*r17 = r7 * (1 - 1.1241 * r12 / r16 *
|
||||||
|
exp (-0.026 * pow (fn, 1.15656) - r15));
|
||||||
|
*ZlEffFreq = ZlEff * pow (r13 / r14, *r17);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The function calculates the conductor and dielectric losses of a
|
||||||
|
* single microstrip line. */
|
||||||
|
void analyseLoss (double W, double t, double er,
|
||||||
|
double rho, double D, double tand,
|
||||||
|
double ZlEff1, double ZlEff2,
|
||||||
|
double ErEff,
|
||||||
|
double frequency, int Model,
|
||||||
|
double* ac, double* ad) {
|
||||||
|
*ac = *ad = 0;
|
||||||
|
|
||||||
|
// HAMMERSTAD and JENSEN
|
||||||
|
if (Model == HAMMERSTAD) {
|
||||||
|
double Rs, ds, l0, Kr, Ki;
|
||||||
|
|
||||||
|
// conductor losses
|
||||||
|
if (t != 0.0) {
|
||||||
|
Rs = sqrt (M_PI * frequency * MU0 * rho); // skin resistance
|
||||||
|
ds = rho / Rs; // skin depth
|
||||||
|
// valid for t > 3 * ds
|
||||||
|
if (t < 3 * ds && frequency != 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
"WARNING: conductor loss calculation invalid for line "
|
||||||
|
"height t (%g) < 3 * skin depth (%g)\n", t, 3 * ds);
|
||||||
|
}
|
||||||
|
// current distribution factor
|
||||||
|
Ki = exp (-1.2 * pow ((ZlEff1 + ZlEff2) / 2 / Z0, 0.7));
|
||||||
|
// D is RMS surface roughness
|
||||||
|
Kr = 1 + M_2_PI * atan (1.4 * sqr (D / ds));
|
||||||
|
*ac = Rs / (ZlEff1 * W) * Ki * Kr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dielectric losses
|
||||||
|
l0 = C0 / frequency;
|
||||||
|
*ad = M_PI * er / (er - 1) * (ErEff - 1) / sqrt (ErEff) * tand / l0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* msline_common.h
|
||||||
|
* common definitions for microstrip devices
|
||||||
|
* (c) Vadim Kuznetsov 2025
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef MSLINE_COMMON_H
|
||||||
|
#define MSLINE_COMMON_H
|
||||||
|
|
||||||
|
//TRAN model
|
||||||
|
#define TRAN_DC 0
|
||||||
|
#define TRAN_FULL 1
|
||||||
|
|
||||||
|
// MS line model
|
||||||
|
#define HAMMERSTAD 0
|
||||||
|
#define KIRSCHING 1
|
||||||
|
#define WHEELER 2
|
||||||
|
#define SCHNEIDER 3
|
||||||
|
|
||||||
|
|
||||||
|
// Dispersion model
|
||||||
|
#define DISP_KIRSCHING 0
|
||||||
|
#define KOBAYASHI 1
|
||||||
|
#define YAMASHITA 2
|
||||||
|
#define DISP_HAMMERSTAD 3
|
||||||
|
#define GETSINGER 4
|
||||||
|
#define DISP_SCHNEIDER 5
|
||||||
|
#define PRAMANICK 6
|
||||||
|
|
||||||
|
void Hammerstad_ab (double, double,
|
||||||
|
double*, double*);
|
||||||
|
void Hammerstad_er (double, double, double,
|
||||||
|
double, double*);
|
||||||
|
void Hammerstad_zl (double, double*);
|
||||||
|
void Getsinger_disp (double, double, double,
|
||||||
|
double, double,
|
||||||
|
double*, double*);
|
||||||
|
void Kirschning_er (double, double, double,
|
||||||
|
double, double*);
|
||||||
|
void Kirschning_zl (double, double, double,
|
||||||
|
double, double, double,
|
||||||
|
double*, double*);
|
||||||
|
|
||||||
|
void mslineAnalyseQuasiStatic (double W, double h, double t,
|
||||||
|
double er, int Model,
|
||||||
|
double *ZlEff, double *ErEff,
|
||||||
|
double *WEff);
|
||||||
|
|
||||||
|
void mslineAnalyseDispersion (double W, double h, double er,
|
||||||
|
double ZlEff, double ErEff,
|
||||||
|
double frequency, int Model,
|
||||||
|
double* ZlEffFreq,
|
||||||
|
double* ErEffFreq);
|
||||||
|
|
||||||
|
void analyseLoss (double, double, double, double,
|
||||||
|
double, double, double, double,
|
||||||
|
double, double, int,
|
||||||
|
double*, double*);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* tline_common.c
|
||||||
|
* common definitions for all transmission lines
|
||||||
|
* (c) Vadim Kuznetsov 2025
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "tline_common.h"
|
||||||
|
|
||||||
|
void append_state(tline_state_t **first, double time, double V1, double V2,
|
||||||
|
double I1, double I2, double tmax)
|
||||||
|
{
|
||||||
|
tline_state_t *pp = (tline_state_t *) malloc(sizeof(tline_state_t));
|
||||||
|
|
||||||
|
pp->next = NULL;
|
||||||
|
pp->time = time;
|
||||||
|
pp->V1 = V1; pp->I1 = I1;
|
||||||
|
pp->V2 = V2; pp->I2 = I2;
|
||||||
|
|
||||||
|
if (*first == NULL) {
|
||||||
|
*first = pp;
|
||||||
|
} else {
|
||||||
|
tline_state_t *pn = *first;
|
||||||
|
while (pn->next != NULL) {
|
||||||
|
pn = pn->next;
|
||||||
|
}
|
||||||
|
pn->next = pp;
|
||||||
|
|
||||||
|
double t0 = (*first)->time;
|
||||||
|
|
||||||
|
if ((time - t0) > tmax) {
|
||||||
|
tline_state_t *new_first = (*first)->next;
|
||||||
|
free(*first);
|
||||||
|
*first = new_first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tline_state_t *get_state(tline_state_t *first, double time)
|
||||||
|
{
|
||||||
|
tline_state_t *pp = first;
|
||||||
|
while (pp != NULL && pp->time < time) {
|
||||||
|
pp = pp->next;
|
||||||
|
}
|
||||||
|
return pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void append_cpline_state(cpline_state_t **first, double time, double *Vp, double *Ip, double tmax)
|
||||||
|
{
|
||||||
|
cpline_state_t *pp = (cpline_state_t *) malloc(sizeof(cpline_state_t));
|
||||||
|
|
||||||
|
pp->next = NULL;
|
||||||
|
pp->time = time;
|
||||||
|
memcpy(pp->Vp, Vp, PORT_NUM*sizeof(double));
|
||||||
|
memcpy(pp->Ip, Ip, PORT_NUM*sizeof(double));
|
||||||
|
|
||||||
|
if (*first == NULL) {
|
||||||
|
*first = pp;
|
||||||
|
} else {
|
||||||
|
cpline_state_t *pn = *first;
|
||||||
|
while (pn->next != NULL) {
|
||||||
|
pn = pn->next;
|
||||||
|
}
|
||||||
|
pn->next = pp;
|
||||||
|
|
||||||
|
double t0 = (*first)->time;
|
||||||
|
|
||||||
|
if ((time - t0) > tmax) {
|
||||||
|
cpline_state_t *new_first = (*first)->next;
|
||||||
|
free(*first);
|
||||||
|
*first = new_first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cpline_state_t *find_cpline_state(cpline_state_t *first, double time)
|
||||||
|
{
|
||||||
|
cpline_state_t *pp = first;
|
||||||
|
while (pp != NULL && pp->time < time) {
|
||||||
|
pp = pp->next;
|
||||||
|
}
|
||||||
|
return pp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* tline_common.h
|
||||||
|
* common definitions for all transmission lines
|
||||||
|
* (c) Vadim Kuznetsov 2025
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TLINE_COMMON_H
|
||||||
|
#define TLINE_COMMON_H
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
#define Z0 (120*M_PI)
|
||||||
|
#define z0 50.0
|
||||||
|
#define MU0 (4*M_PI*1e-7)
|
||||||
|
|
||||||
|
#define C0 299792458.0
|
||||||
|
|
||||||
|
#define GMIN 1e-12
|
||||||
|
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
#define sqr(x) (x*x)
|
||||||
|
#define cubic(x) (x*x*x)
|
||||||
|
#define quadr(x) (x*x*x*x)
|
||||||
|
|
||||||
|
#define coth(x) (1.0/tanh(x))
|
||||||
|
#define sech(x) (1.0/cosh(x))
|
||||||
|
#define cosech(x) (1.0/sinh(x))
|
||||||
|
|
||||||
|
// Data structures to hold transient state
|
||||||
|
|
||||||
|
typedef struct tline_state {
|
||||||
|
double time;
|
||||||
|
double I1;
|
||||||
|
double I2;
|
||||||
|
double V1;
|
||||||
|
double V2;
|
||||||
|
|
||||||
|
struct tline_state *next;
|
||||||
|
} tline_state_t;
|
||||||
|
|
||||||
|
// Functions to retrieve previous transient state
|
||||||
|
void append_state(tline_state_t **first, double time, double V1, double V2,
|
||||||
|
double I1, double I2, double tmax);
|
||||||
|
|
||||||
|
tline_state_t *get_state(tline_state_t *first, double time);
|
||||||
|
|
||||||
|
#define PORT_NUM 4
|
||||||
|
|
||||||
|
typedef struct cpline_state {
|
||||||
|
double time;
|
||||||
|
double Ip[PORT_NUM];
|
||||||
|
double Vp[PORT_NUM];
|
||||||
|
|
||||||
|
struct cpline_state *next;
|
||||||
|
} cpline_state_t;
|
||||||
|
|
||||||
|
void append_cpline_state(cpline_state_t **first, double time, double *Vp, double *Ip, double tmax);
|
||||||
|
|
||||||
|
cpline_state_t *find_cpline_state(cpline_state_t *first, double time);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue