committed by
Holger Vogt
16 changed files with 2095 additions and 4 deletions
-
1src/spinit.in
-
18src/xspice/icm/GNUmakefile.in
-
158src/xspice/icm/tlines/cpline/cfunc.mod
-
176src/xspice/icm/tlines/cpline/ifspec.ifs
-
496src/xspice/icm/tlines/cpmlin/cfunc.mod
-
216src/xspice/icm/tlines/cpmlin/ifspec.ifs
-
133src/xspice/icm/tlines/mlin/cfunc.mod
-
173src/xspice/icm/tlines/mlin/ifspec.ifs
-
4src/xspice/icm/tlines/modpath.lst
-
91src/xspice/icm/tlines/tline/cfunc.mod
-
87src/xspice/icm/tlines/tline/ifspec.ifs
-
0src/xspice/icm/tlines/udnpath.lst
-
337src/xspice/tlines/msline_common.c
-
60src/xspice/tlines/msline_common.h
-
86src/xspice/tlines/tline_common.c
-
63src/xspice/tlines/tline_common.h
@ -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 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue