You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1135 lines
24 KiB
1135 lines
24 KiB
/**********
|
|
Copyright 1992 Regents of the University of California. All rights
|
|
reserved.
|
|
Author: 1992 Charles Hough
|
|
**********/
|
|
|
|
|
|
#include "ngspice.h"
|
|
#include "smpdefs.h"
|
|
#include "txldefs.h"
|
|
#include "sperror.h"
|
|
#include "suffix.h"
|
|
|
|
#include "../cap/capdefs.h"
|
|
|
|
static int ReadTxL();
|
|
/*static int multC();*/
|
|
static int main_pade();
|
|
static int mac();
|
|
/*static int divC();*/
|
|
static int div_C();
|
|
static int div3();
|
|
/*static double approx1();*/
|
|
/*static double approx2();*/
|
|
static int find_roots();
|
|
/*static double f3();*/
|
|
/*static double f2();*/
|
|
/*static int expC();*/
|
|
/*static double exp_approx1();*/
|
|
/*static double exp_approx2();*/
|
|
static int exp_pade();
|
|
/*static int exp_div3();*/
|
|
static int exp_find_roots();
|
|
static double eval2();
|
|
static int get_c();
|
|
static int get_h3();
|
|
static int Gaussian_Elimination2();
|
|
static int Gaussian_Elimination1();
|
|
static int pade();
|
|
static int update_h1C_c();
|
|
static void y_pade();
|
|
static double root3();
|
|
static NDnamePt insert_ND();
|
|
static NODE *insert_node();
|
|
static NODE *NEW_node();
|
|
/*static VI_list_txl *new_vi_txl();*/
|
|
|
|
NODE *node_tab = NULL;
|
|
NDnamePt ndn = NULL;
|
|
VI_list_txl *pool_vi_txl = NULL;
|
|
|
|
/* pade.c */
|
|
/**
|
|
static double xx1, xx2, xx3, xx4, xx5, xx6;
|
|
static double cc1, cc2, cc3, cc4, cc5, cc6;
|
|
**/
|
|
|
|
/* y.c */
|
|
static double sqtCdL;
|
|
static double b1, b2, b3, b4, b5;
|
|
static double p1, p2, p3, q1, q2, q3;
|
|
static double c1, c2, c3, x1, x2, x3;
|
|
static double A[3][4];
|
|
|
|
/* exp.c */
|
|
static double RdL, GdC, RG, tau, RC, GL;
|
|
static double a0, a1, a2, a3, a4, a5;
|
|
static double ep1, ep2, ep3, eq1, eq2, eq3;
|
|
static double ec1, ec2, ec3, ex1, ex2, ex3;
|
|
static int ifImg;
|
|
static double AA[3][4];
|
|
|
|
#define epsi 1.0e-16
|
|
#define epsi2 1.0e-28
|
|
|
|
/* ARGSUSED */
|
|
int
|
|
TXLsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit*ckt, int *state)
|
|
{
|
|
TXLmodel *model = (TXLmodel *)inModel;
|
|
TXLinstance *here;
|
|
CKTnode *tmp;
|
|
int error;
|
|
|
|
/* loop through all the models */
|
|
for( ; model != NULL; model = model->TXLnextModel ) {
|
|
|
|
/* loop through all the instances of the model */
|
|
for (here = model->TXLinstances; here != NULL ;
|
|
here=here->TXLnextInstance) {
|
|
|
|
/* macro to make elements with built in test for out of memory */
|
|
#define TSTALLOC(ptr,first,second) \
|
|
if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\
|
|
return(E_NOMEM);\
|
|
}
|
|
|
|
if (! here->TXLibr1Given) {
|
|
error = CKTmkCur(ckt, &tmp, here->TXLname, "branch1");
|
|
if (error) return (error);
|
|
here->TXLibr1 = tmp->number;
|
|
}
|
|
if (! here->TXLibr2Given) {
|
|
error = CKTmkCur(ckt, &tmp, here->TXLname, "branch2");
|
|
if (error) return (error);
|
|
here->TXLibr2 = tmp->number;
|
|
}
|
|
|
|
TSTALLOC(TXLposPosptr, TXLposNode, TXLposNode);
|
|
TSTALLOC(TXLposNegptr, TXLposNode, TXLnegNode);
|
|
TSTALLOC(TXLnegPosptr, TXLnegNode, TXLposNode);
|
|
TSTALLOC(TXLnegNegptr, TXLnegNode, TXLnegNode);
|
|
TSTALLOC(TXLibr1Posptr, TXLibr1, TXLposNode);
|
|
TSTALLOC(TXLibr2Negptr, TXLibr2, TXLnegNode);
|
|
TSTALLOC(TXLnegIbr2ptr, TXLnegNode, TXLibr2);
|
|
TSTALLOC(TXLposIbr1ptr, TXLposNode, TXLibr1);
|
|
TSTALLOC(TXLibr1Ibr1ptr, TXLibr1, TXLibr1);
|
|
TSTALLOC(TXLibr2Ibr2ptr, TXLibr2, TXLibr2);
|
|
TSTALLOC(TXLibr1Negptr, TXLibr1, TXLnegNode);
|
|
TSTALLOC(TXLibr2Posptr, TXLibr2, TXLposNode);
|
|
TSTALLOC(TXLibr1Ibr2ptr, TXLibr1, TXLibr2);
|
|
TSTALLOC(TXLibr2Ibr1ptr, TXLibr2, TXLibr1);
|
|
|
|
here->in_node_name = CKTnodName(ckt,here->TXLposNode);
|
|
here->out_node_name = CKTnodName(ckt,here->TXLnegNode);
|
|
ReadTxL(here, ckt);
|
|
|
|
}
|
|
}
|
|
|
|
return(OK);
|
|
}
|
|
|
|
/***
|
|
static VI_list_txl
|
|
*new_vi_txl()
|
|
{
|
|
VI_list_txl *q;
|
|
|
|
if (pool_vi_txl) {
|
|
q = pool_vi_txl;
|
|
pool_vi_txl = pool_vi_txl->pool;
|
|
return(q);
|
|
} else
|
|
return((VI_list_txl *) malloc (sizeof (VI_list_txl)));
|
|
}
|
|
***/
|
|
|
|
static int ReadTxL(tx, ckt)
|
|
TXLinstance *tx;
|
|
CKTcircuit *ckt;
|
|
{
|
|
double R, L, G, C, l;
|
|
char *p, *n;
|
|
NODE *nd;
|
|
ETXLine *et;
|
|
TXLine *t, *t2;
|
|
RLINE *line;
|
|
ERLINE *er;
|
|
double LL = 1e-12;
|
|
|
|
p = tx->in_node_name;
|
|
n = tx->out_node_name;
|
|
|
|
line = (RLINE *) malloc(sizeof (RLINE));
|
|
er = (ERLINE *) malloc(sizeof (ERLINE));
|
|
et = (ETXLine *) malloc(sizeof (ETXLine));
|
|
t = (TXLine *) malloc(sizeof (TXLine));
|
|
t2 = (TXLine *) malloc(sizeof (TXLine));
|
|
tx->txline = t;
|
|
tx->txline2 = t2;
|
|
t->newtp = 0;
|
|
t2->newtp = 0;
|
|
t->vi_head = t->vi_tail = NULL;
|
|
nd = insert_node(p);
|
|
et->link = nd->tptr;
|
|
nd->tptr = et;
|
|
et->line = t;
|
|
t->in_node = nd;
|
|
t2->in_node = nd;
|
|
er->link = nd->rlptr;
|
|
nd->rlptr = er;
|
|
er->rl = line;
|
|
line->in_node = nd;
|
|
et = (ETXLine *) malloc(sizeof (ETXLine));
|
|
nd = insert_node(n);
|
|
et->link = nd->tptr;
|
|
nd->tptr = et;
|
|
et->line = t;
|
|
t->out_node = nd;
|
|
t2->out_node = nd;
|
|
er = (ERLINE *) malloc(sizeof (ERLINE));
|
|
er->link = nd->rlptr;
|
|
nd->rlptr = er;
|
|
er->rl = line;
|
|
line->out_node = nd;
|
|
t->dc1 = t->dc2 = 0.0;
|
|
t2->dc1 = t2->dc2 = 0.0;
|
|
t->lsl = 0;
|
|
t2->lsl = 0;
|
|
l = 0.0;
|
|
|
|
R = tx->TXLmodPtr->R;
|
|
L = tx->TXLmodPtr->L;
|
|
L = MAX(L, LL);
|
|
C = tx->TXLmodPtr->C;
|
|
G = tx->TXLmodPtr->G;
|
|
if (tx->TXLlengthgiven == TRUE)
|
|
l = tx->TXLlength;
|
|
else l = tx->TXLmodPtr->length;
|
|
|
|
|
|
if (l == 0.0) {
|
|
fprintf(stderr, "(Error) transmission line of zero length\n");
|
|
exit(0);
|
|
}
|
|
else {
|
|
if (R / L < 5.0e+5) {
|
|
line->g = 1.0e+2;
|
|
if (G < 1.0e-2) {
|
|
t->lsl = 1; /* lossless line */
|
|
t->taul = sqrt((double) C * L) * l * 1.0e12;
|
|
t->h3_aten = t->sqtCdL = sqrt((double) C / L);
|
|
t->h2_aten = 1.0;
|
|
t->h1C = 0.0;
|
|
}
|
|
}
|
|
else line->g = 1.0 / (R * l);
|
|
}
|
|
|
|
if (! t->lsl)
|
|
main_pade(R, L, G, C, l, t);
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
pade.c : Calculate the Pade Approxximation of Y(s)
|
|
****************************************************************/
|
|
|
|
|
|
static int main_pade(R, L, G, C, l, h)
|
|
double R, L, G, C, l;
|
|
TXLine *h;
|
|
{
|
|
y_pade(R, L, G, C, h);
|
|
h->ifImg = exp_pade(R, L, G, C, l, h);
|
|
get_h3(h);
|
|
h->taul *= 1.0e12;
|
|
update_h1C_c(h);
|
|
|
|
return(1);
|
|
}
|
|
|
|
static int div_C(ar, ai, br, bi, cr, ci)
|
|
double ar, ai, br, bi;
|
|
double *cr, *ci;
|
|
{
|
|
*cr = ar * br + ai * bi;
|
|
*ci = - ar * bi + ai * br;
|
|
*cr = *cr / (br * br + bi * bi);
|
|
*ci = *ci / (br * br + bi * bi);
|
|
return (1);
|
|
}
|
|
|
|
/***
|
|
static int expC(ar, ai, h, cr, ci)
|
|
double ar, ai, *cr, *ci;
|
|
float h;
|
|
{
|
|
double e, cs, si;
|
|
|
|
e = exp((double) ar * h);
|
|
cs = cos((double) ai * h);
|
|
si = sin((double) ai * h);
|
|
*cr = e * cs;
|
|
*ci = e * si;
|
|
|
|
return(1);
|
|
}
|
|
***/
|
|
|
|
/***
|
|
static int multC(ar, ai, br, bi, cr, ci)
|
|
double ar, ai, br, bi;
|
|
double *cr, *ci;
|
|
{
|
|
*cr = ar*br - ai*bi;
|
|
*ci = ar*bi + ai*br;
|
|
|
|
return(1);
|
|
}
|
|
***/
|
|
|
|
/***
|
|
static int divC(ar, ai, br, bi, cr, ci)
|
|
double ar, ai, br, bi;
|
|
double *cr, *ci;
|
|
{
|
|
double t;
|
|
t = br*br + bi*bi;
|
|
*cr = (ar*br + ai*bi) / t;
|
|
*ci = (ai*br - ar*bi) / t;
|
|
|
|
return(1);
|
|
}
|
|
***/
|
|
|
|
static int get_h3(h)
|
|
TXLine *h;
|
|
{
|
|
double cc1, cc2, cc3, cc4, cc5, cc6;
|
|
double xx1, xx2, xx3, xx4, xx5, xx6;
|
|
|
|
h->h3_aten = h->h2_aten * h->sqtCdL;
|
|
h->h3_term[0].x = xx1 = h->h1_term[0].x;
|
|
h->h3_term[1].x = xx2 = h->h1_term[1].x;
|
|
h->h3_term[2].x = xx3 = h->h1_term[2].x;
|
|
h->h3_term[3].x = xx4 = h->h2_term[0].x;
|
|
h->h3_term[4].x = xx5 = h->h2_term[1].x;
|
|
h->h3_term[5].x = xx6 = h->h2_term[2].x;
|
|
cc1 = h->h1_term[0].c;
|
|
cc2 = h->h1_term[1].c;
|
|
cc3 = h->h1_term[2].c;
|
|
cc4 = h->h2_term[0].c;
|
|
cc5 = h->h2_term[1].c;
|
|
cc6 = h->h2_term[2].c;
|
|
|
|
if (h->ifImg) {
|
|
double r, i;
|
|
|
|
h->h3_term[0].c = cc1 + cc1 * (cc4/(xx1-xx4) +
|
|
2.0*(cc5*xx1-xx6*cc6-xx5*cc5)/(xx1*xx1-2.0*xx5*xx1+xx5*xx5+xx6*xx6));
|
|
h->h3_term[1].c = cc2 + cc2 * (cc4/(xx2-xx4) +
|
|
2.0*(cc5*xx2-xx6*cc6-xx5*cc5)/(xx2*xx2-2.0*xx5*xx2+xx5*xx5+xx6*xx6));
|
|
h->h3_term[2].c = cc3 + cc3 * (cc4/(xx3-xx4) +
|
|
2.0*(cc5*xx3-xx6*cc6-xx5*cc5)/(xx3*xx3-2.0*xx5*xx3+xx5*xx5+xx6*xx6));
|
|
|
|
h->h3_term[3].c = cc4 + cc4 * (cc1/(xx4-xx1) + cc2/(xx4-xx2) + cc3/(xx4-xx3));
|
|
|
|
h->h3_term[4].c = cc5;
|
|
h->h3_term[5].c = cc6;
|
|
div_C(cc5, cc6, xx5-xx1, xx6, &r, &i);
|
|
h->h3_term[4].c += r * cc1;
|
|
h->h3_term[5].c += i * cc1;
|
|
div_C(cc5, cc6, xx5-xx2, xx6, &r, &i);
|
|
h->h3_term[4].c += r * cc2;
|
|
h->h3_term[5].c += i * cc2;
|
|
div_C(cc5, cc6, xx5-xx3, xx6, &r, &i);
|
|
h->h3_term[4].c += r * cc3;
|
|
h->h3_term[5].c += i * cc3;
|
|
} else {
|
|
h->h3_term[0].c = cc1 + cc1 * (cc4/(xx1-xx4) + cc5/(xx1-xx5) + cc6/(xx1-xx6));
|
|
h->h3_term[1].c = cc2 + cc2 * (cc4/(xx2-xx4) + cc5/(xx2-xx5) + cc6/(xx2-xx6));
|
|
h->h3_term[2].c = cc3 + cc3 * (cc4/(xx3-xx4) + cc5/(xx3-xx5) + cc6/(xx3-xx6));
|
|
|
|
h->h3_term[3].c = cc4 + cc4 * (cc1/(xx4-xx1) + cc2/(xx4-xx2) + cc3/(xx4-xx3));
|
|
h->h3_term[4].c = cc5 + cc5 * (cc1/(xx5-xx1) + cc2/(xx5-xx2) + cc3/(xx5-xx3));
|
|
h->h3_term[5].c = cc6 + cc6 * (cc1/(xx6-xx1) + cc2/(xx6-xx2) + cc3/(xx6-xx3));
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
|
|
static int update_h1C_c(h)
|
|
TXLine *h;
|
|
{
|
|
int i;
|
|
double d = 0;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
h->h1_term[i].c *= h->sqtCdL;
|
|
d += h->h1_term[i].c;
|
|
}
|
|
h->h1C = d;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
h->h2_term[i].c *= h->h2_aten;
|
|
|
|
for (i = 0; i < 6; i++)
|
|
h->h3_term[i].c *= h->h3_aten;
|
|
|
|
return(1);
|
|
}
|
|
/****************************************************************
|
|
y.c : Calculate the Pade Approximation of Y(s)
|
|
****************************************************************/
|
|
|
|
|
|
static double eval2(a, b, c, x)
|
|
double a, b, c, x;
|
|
{
|
|
return(a*x*x + b*x + c);
|
|
}
|
|
|
|
/***
|
|
static double approx1(st)
|
|
double st;
|
|
{
|
|
double s3, s2, s1;
|
|
|
|
s1 = st;
|
|
s2 = s1 * s1;
|
|
s3 = s2 * s1;
|
|
|
|
return((s3 + q1*s2 + q2*s1 + q3) / (s3 + p1*s2 + p2*s1 + p3));
|
|
}
|
|
***/
|
|
/***
|
|
static double approx2(st)
|
|
double st;
|
|
{
|
|
return(1.0 + c1/(st - x1) + c2/(st - x2) + c3/(st - x3));
|
|
}
|
|
***/
|
|
|
|
static void y_pade(R, L, G, C, h)
|
|
double R, L, G, C;
|
|
TXLine *h;
|
|
{
|
|
|
|
/* float RdL, GdC; */
|
|
double RdL, GdC;
|
|
|
|
sqtCdL = sqrt((double) C / L);
|
|
RdL = R / L;
|
|
GdC = G / C;
|
|
|
|
mac(GdC, RdL, &b1, &b2, &b3, &b4, &b5);
|
|
|
|
A[0][0] = 1.0 - sqrt((double) (GdC / RdL));
|
|
A[0][1] = b1;
|
|
A[0][2] = b2;
|
|
A[0][3] = -b3;
|
|
|
|
A[1][0] = b1;
|
|
A[1][1] = b2;
|
|
A[1][2] = b3;
|
|
A[1][3] = -b4;
|
|
|
|
A[2][0] = b2;
|
|
A[2][1] = b3;
|
|
A[2][2] = b4;
|
|
A[2][3] = -b5;
|
|
|
|
Gaussian_Elimination1(3);
|
|
|
|
p3 = A[0][3];
|
|
p2 = A[1][3];
|
|
p1 = A[2][3];
|
|
|
|
q1 = p1 + b1;
|
|
q2 = b1 * p1 + p2 + b2;
|
|
q3 = p3 * sqrt((double) (GdC / RdL));
|
|
|
|
find_roots(p1, p2, p3, &x1, &x2, &x3);
|
|
c1 = eval2(q1 - p1, q2 - p2, q3 - p3, x1) /
|
|
eval2((double) 3.0, (double) 2.0 * p1, p2, x1);
|
|
c2 = eval2(q1 - p1, q2 - p2, q3 - p3, x2) /
|
|
eval2((double) 3.0, (double) 2.0 * p1, p2, x2);
|
|
c3 = eval2(q1 - p1, q2 - p2, q3 - p3, x3) /
|
|
eval2((double) 3.0, (double) 2.0 * p1, p2, x3);
|
|
|
|
h->sqtCdL = sqtCdL;
|
|
h->h1_term[0].c = c1;
|
|
h->h1_term[1].c = c2;
|
|
h->h1_term[2].c = c3;
|
|
h->h1_term[0].x = x1;
|
|
h->h1_term[1].x = x2;
|
|
h->h1_term[2].x = x3;
|
|
|
|
}
|
|
|
|
static int Gaussian_Elimination1(dims)
|
|
int dims;
|
|
{
|
|
register int i, j, k, dim;
|
|
register double f;
|
|
int imax;
|
|
double max;
|
|
|
|
dim = dims;
|
|
|
|
for (i = 0; i < dim; i++) {
|
|
imax = i;
|
|
max = ABS(A[i][i]);
|
|
for (j = i+1; j < dim; j++)
|
|
if (ABS(A[j][i]) > max) {
|
|
imax = j;
|
|
max = ABS(A[j][i]);
|
|
}
|
|
if (max < epsi) {
|
|
fprintf(stderr, " can not choose a pivot \n");
|
|
exit(0);
|
|
}
|
|
if (imax != i)
|
|
for (k = i; k <= dim; k++) {
|
|
f = A[i][k];
|
|
A[i][k] = A[imax][k];
|
|
A[imax][k] = f;
|
|
}
|
|
|
|
f = 1.0 / A[i][i];
|
|
A[i][i] = 1.0;
|
|
|
|
for (j = i+1; j <= dim; j++)
|
|
A[i][j] *= f;
|
|
|
|
for (j = 0; j < dim ; j++) {
|
|
if (i == j)
|
|
continue;
|
|
f = A[j][i];
|
|
A[j][i] = 0.0;
|
|
for (k = i+1; k <= dim; k++)
|
|
A[j][k] -= f * A[i][k];
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
static double root3(a1, a2, a3, x)
|
|
double x;
|
|
double a1, a2, a3;
|
|
{
|
|
double t1, t2;
|
|
|
|
t1 = x*x*x + a1*x*x + a2*x + a3;
|
|
t2 = 3.0*x*x + 2.0*a1*x + a2;
|
|
|
|
return(x - t1 / t2);
|
|
}
|
|
|
|
static int div3(a1, a2, a3, x, p1, p2)
|
|
double x;
|
|
double a1, a2, a3;
|
|
double *p1, *p2;
|
|
{
|
|
*p1 = a1 + x;
|
|
*p2 = - a3 / x;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/****************************************************************
|
|
Calculate the Maclaurin series of F(z)
|
|
|
|
F(z) = sqrt((1+az) / (1+bz))
|
|
= 1 + b1 z + b2 z^2 + b3 z^3 + b4 z^4 + b5 z^5
|
|
****************************************************************/
|
|
|
|
/***
|
|
static double f3(a, b, z)
|
|
double a, b, z;
|
|
{
|
|
double t4, t3, t2, t1;
|
|
double t14, t13, t12, t11;
|
|
double sqt11;
|
|
|
|
t1 = 1 / (1.0 + b * z);
|
|
t2 = t1 * t1;
|
|
t3 = t2 * t1;
|
|
t4 = t3 * t1;
|
|
|
|
t11 = (1.0 + a * z) * t1;
|
|
t12 = (1.0 + a * z) * t2;
|
|
t13 = (1.0 + a * z) * t3;
|
|
t14 = (1.0 + a * z) * t4;
|
|
|
|
sqt11 = sqrt(t11);
|
|
|
|
|
|
return(
|
|
-0.5 * (-2.0*a*b*t2 + 2.0*b*b*t13) * (a*t1 - b*t12) / (t11*sqt11)
|
|
+3.0/8.0 * (a*t1-b*t12)*(a*t1-b*t12)*(a*t1-b*t12) / (t11*t11*sqt11)
|
|
+0.5 * (4.0*a*b*b*t3 + 2.0*a*b*b*t3 - 6.0*b*b*b*t14) / sqt11
|
|
-0.25 * (-2.0*a*b*t2 + 2.0*b*b*t13) * (a*t1-b*(1.0+a*z)) /
|
|
(t11*sqt11)
|
|
);
|
|
}
|
|
***/
|
|
|
|
/***
|
|
static double f2(a, b, z)
|
|
double a, b, z;
|
|
{
|
|
double t3, t2, t1;
|
|
double t13, t12, t11;
|
|
double sqt11;
|
|
|
|
t1 = 1 / (1.0 + b * z);
|
|
t2 = t1 * t1;
|
|
t3 = t2 * t1;
|
|
|
|
t11 = (1.0 + a * z) * t1;
|
|
t12 = (1.0 + a * z) * t2;
|
|
t13 = (1.0 + a * z) * t3;
|
|
|
|
sqt11 = sqrt(t11);
|
|
|
|
return(
|
|
-0.25 * (a*t1-b*t12) * (a*t1-b*t12) / (t11*sqt11)
|
|
+0.5 * (-2.0*a*b*t2 + 2.0*b*b*t13) / sqt11
|
|
);
|
|
}
|
|
***/
|
|
|
|
static int mac(at, bt, b1, b2, b3, b4, b5)
|
|
/* float at, bt; */
|
|
double at, bt;
|
|
double *b1, *b2, *b3, *b4, *b5;
|
|
{
|
|
double a, b;
|
|
double y1, y2, y3, y4, y5;
|
|
|
|
a = at;
|
|
b = bt;
|
|
|
|
y1 = *b1 = 0.5 * (a - b);
|
|
y2 = 0.5 * (3.0 * b * b - 2.0 * a * b - a * a) * y1 / (a - b);
|
|
y3 = ((3.0 * b * b + a * a) * y1 * y1 + 0.5 * (3.0 * b * b
|
|
- 2.0 * a * b - a * a) * y2) / (a - b);
|
|
y4 = ((3.0 * b * b - 3.0 * a * a) * y1 * y1 * y1 + (9.0 * b * b
|
|
+ 3.0 * a * a) * y1 * y2 + 0.5 * (3.0 * b * b - 2.0 * a * b
|
|
- a * a) * y3) / (a - b);
|
|
y5 = (12.0 * a * a * y1 * y1 * y1 * y1 + y1 * y1 * y2 * (
|
|
18.0 * b * b - 18.0 * a * a) + (9.0 * b * b + 3.0 * a * a) *
|
|
(y2 * y2 + y1 * y3) + (3.0 * b * b + a * a) * y1 * y3 +
|
|
0.5 * (3.0 * b * b - 2.0 * a * b - a * a) * y4) / (a - b);
|
|
|
|
*b2 = y2 / 2.0;
|
|
*b3 = y3 / 6.0;
|
|
*b4 = y4 / 24.0;
|
|
*b5 = y5 / 120.0;
|
|
|
|
return(1);
|
|
}
|
|
|
|
|
|
/****************************************************
|
|
exp.c
|
|
****************************************************/
|
|
|
|
/***
|
|
static double exp_approx1(st)
|
|
double st;
|
|
{
|
|
double s3, s2, s1;
|
|
|
|
s1 = st;
|
|
s2 = s1 * s1;
|
|
s3 = s2 * s1;
|
|
|
|
return(exp((double) - st * tau - a0) *
|
|
(s3 + eq1*s2 + eq2*s1 + eq3) / (s3 + ep1*s2 + ep2*s1 + ep3));
|
|
}
|
|
***/
|
|
|
|
static int get_c(eq1, eq2, eq3, ep1, ep2, a, b, cr, ci)
|
|
double eq1, eq2, eq3, ep1, ep2, a, b;
|
|
double *cr, *ci;
|
|
{
|
|
double d, n;
|
|
|
|
d = (3.0*(a*a-b*b)+2.0*ep1*a+ep2)*(3.0*(a*a-b*b)+2.0*ep1*a+ep2);
|
|
d += (6.0*a*b+2.0*ep1*b)*(6.0*a*b+2.0*ep1*b);
|
|
n = -(eq1*(a*a-b*b)+eq2*a+eq3)*(6.0*a*b+2.0*ep1*b);
|
|
n += (2.0*eq1*a*b+eq2*b)*(3.0*(a*a-b*b)+2.0*ep1*a+ep2);
|
|
*ci = n/d;
|
|
n = (3.0*(a*a-b*b)+2.0*ep1*a+ep2)*(eq1*(a*a-b*b)+eq2*a+eq3);
|
|
n += (6.0*a*b+2.0*ep1*b)*(2.0*eq1*a*b+eq2*b);
|
|
*cr = n/d;
|
|
|
|
return(1);
|
|
}
|
|
|
|
/***
|
|
static double exp_approx2(st)
|
|
double st;
|
|
{
|
|
if (ifImg)
|
|
return(1.0 + ec1/(st - ex1) + 2.0*(ec2*(st-ex2)-ec3*ex3) /
|
|
((st-ex2)*(st-ex2) + ex3*ex3));
|
|
else
|
|
return(1.0 + ec1/(st - ex1) + ec2/(st - ex2) + ec3/(st - ex3));
|
|
}
|
|
***/
|
|
|
|
static int exp_pade(R, L, G, C, l, h)
|
|
float R, L, G, C, l;
|
|
TXLine *h;
|
|
{
|
|
|
|
tau = sqrt((double) L*C);
|
|
RdL = R / L;
|
|
GdC = G / C;
|
|
RG = R * G;
|
|
RC = R * C;
|
|
GL = G * L;
|
|
|
|
{
|
|
double a, b, t;
|
|
double y1, y2, y3, y4, y5, y6;
|
|
|
|
a = RdL;
|
|
b = GdC;
|
|
t = tau;
|
|
|
|
/*
|
|
y1 = 0.5 * (a + b);
|
|
y2 = a * b - y1 * y1;
|
|
y3 = - a * b * y1 - 2.0 * y1 * y2 + y1 * y1 * y1;
|
|
y4 = 2.0 * a * b * y1 * y1 - a * b * y2 - 2.0 * y2 * y2
|
|
- 2.0 * y1 * y3 + 5.0 * y1 * y1 * y2
|
|
- 2.0 * y1 * y1 * y1 * y1;
|
|
y5 = 6.0 * a * b * (y1 * y2 - y1 * y1 * y1) - a * b * y3
|
|
- 2.0 * y1 * y4
|
|
- 6.0 * y2 * y3 + 12.0 * y2 * y2 * y1 + 7.0 * y1 * y1 * y3
|
|
-10.0 * y1 * y1 * y1 * y2 - 8.0 * y1 * y1 * y1 * y2
|
|
+ 6.0 * y1 * y1 * y1 * y1 * y1;
|
|
y6 = 24.0 * a * b * y1 * y1 * y1 * y1 - 36.0 * a * b * y1 * y1 * y2
|
|
+ 6.0 * a * b * y2 * y2 + 8.0 * a * b * y1 * y3 - 2.0 * y2 * y4
|
|
- 2.0 * y1 * y5 + 2.0 * y1 * y1 * y4 - a * b * y4 -6.0 * y3 * y3
|
|
+ 44.0 * y1 * y2 * y3 + 60.0 * y1 * y1 * y1 * y1 * y2
|
|
-24.0 * y1 * y1 * y1 * y1 * y1 * y1 + 12.0 * y2 * y2 * y2
|
|
-54.0 * y1 * y1 * y2 * y2 + 7.0 * y1 * y1 * y4
|
|
-24.0 * y1 * y1 * y1 * y3 - 24.0 * y1 * y1 * y2 * y2
|
|
-8.0 * y1 * y1 * y1 * y3 + 24.0 * y1 * y1 * y1 * y1 * y2
|
|
- 6.0 * y2 * y4;
|
|
*/
|
|
|
|
y1 = 0.5 * (a + b);
|
|
y2 = a * b - y1 * y1;
|
|
y3 = -3.0 * y1 * y2;
|
|
y4 = -3.0 * y2 * y2 - 4.0 * y1 * y3;
|
|
y5 = - 5.0 * y1 * y4 -10.0 * y2 * y3;
|
|
y6 = -10.0 * y3 * y3 - 15.0 * y2 * y4 - 6.0 * y1 * y5;
|
|
|
|
a0 = y1 * t;
|
|
a1 = y2 * t * t / 2.0;
|
|
a2 = y3 * t * t * t / 6.0;
|
|
a3 = y4 * t * t * t * t / 24.0;
|
|
a4 = y5 * t * t * t * t * t / 120.0;
|
|
a5 = y6 * t * t * t * t * t * t / 720.0;
|
|
|
|
}
|
|
|
|
a0 *= l;
|
|
a1 *= l;
|
|
a2 *= l;
|
|
a3 *= l;
|
|
a4 *= l;
|
|
a5 *= l;
|
|
|
|
pade(l);
|
|
|
|
h->taul = tau * l;
|
|
h->h2_aten = exp(- a0);
|
|
h->h2_term[0].c = ec1;
|
|
h->h2_term[1].c = ec2;
|
|
h->h2_term[2].c = ec3;
|
|
h->h2_term[0].x = ex1;
|
|
h->h2_term[1].x = ex2;
|
|
h->h2_term[2].x = ex3;
|
|
|
|
return(ifImg);
|
|
}
|
|
|
|
static int pade(l)
|
|
float l;
|
|
{
|
|
int i, j;
|
|
double a[6];
|
|
double b[6];
|
|
|
|
a[1] = -a1;
|
|
a[2] = -a2;
|
|
a[3] = -a3;
|
|
a[4] = -a4;
|
|
a[5] = -a5;
|
|
|
|
b[0] = 1.0;
|
|
b[1] = a[1];
|
|
for (i = 2; i <= 5; i++) {
|
|
b[i] = 0.0;
|
|
for (j = 1; j <= i; j++)
|
|
b[i] += j * a[j] * b[i-j];
|
|
b[i] = b[i] / (double) i;
|
|
}
|
|
|
|
AA[0][0] = 1.0 - exp((double) a0 - l * sqrt(RG));
|
|
AA[0][1] = b[1];
|
|
AA[0][2] = b[2];
|
|
AA[0][3] = -b[3];
|
|
|
|
AA[1][0] = b[1];
|
|
AA[1][1] = b[2];
|
|
AA[1][2] = b[3];
|
|
AA[1][3] = -b[4];
|
|
|
|
AA[2][0] = b[2];
|
|
AA[2][1] = b[3];
|
|
AA[2][2] = b[4];
|
|
AA[2][3] = -b[5];
|
|
|
|
Gaussian_Elimination2(3);
|
|
|
|
ep3 = AA[0][3];
|
|
ep2 = AA[1][3];
|
|
ep1 = AA[2][3];
|
|
|
|
eq1 = ep1 + b[1];
|
|
eq2 = b[1] * ep1 + ep2 + b[2];
|
|
eq3 = ep3 * exp((double) a0 - l * sqrt(RG));
|
|
|
|
ep3 = ep3 / (tau*tau*tau);
|
|
ep2 = ep2 / (tau*tau);
|
|
ep1 = ep1 / tau;
|
|
eq3 = eq3 / (tau*tau*tau);
|
|
eq2 = eq2 / (tau*tau);
|
|
eq1 = eq1 / tau;
|
|
/*
|
|
printf("factor = %e\n", exp(-a0));
|
|
printf("ep1 = %e ep2 = %e ep3 = %e\n", ep1, ep2, ep3);
|
|
*/
|
|
exp_find_roots(ep1, ep2, ep3, &ex1, &ex2, &ex3);
|
|
/*
|
|
printf("roots are %e %e %e \n", ex1, ex2, ex3);
|
|
*/
|
|
ec1 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex1) /
|
|
eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex1);
|
|
if (ifImg)
|
|
get_c(eq1 - ep1, eq2 - ep2, eq3 - ep3, ep1, ep2, ex2, ex3, &ec2, &ec3);
|
|
else {
|
|
ec2 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex2) /
|
|
eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex2);
|
|
ec3 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex3) /
|
|
eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex3);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
static int Gaussian_Elimination2(dims)
|
|
int dims;
|
|
{
|
|
register int i, j, k, dim;
|
|
register double f;
|
|
double max;
|
|
int imax;
|
|
|
|
dim = dims;
|
|
|
|
for (i = 0; i < dim; i++) {
|
|
imax = i;
|
|
max = ABS(AA[i][i]);
|
|
for (j = i+1; j < dim; j++)
|
|
if (ABS(AA[j][i]) > max) {
|
|
imax = j;
|
|
max = ABS(AA[j][i]);
|
|
}
|
|
if (max < epsi2) {
|
|
fprintf(stderr, " can not choose a pivot \n");
|
|
exit(0);
|
|
}
|
|
if (imax != i)
|
|
for (k = i; k <= dim; k++) {
|
|
f = AA[i][k];
|
|
AA[i][k] = AA[imax][k];
|
|
AA[imax][k] = f;
|
|
}
|
|
|
|
f = 1.0 / AA[i][i];
|
|
AA[i][i] = 1.0;
|
|
|
|
for (j = i+1; j <= dim; j++)
|
|
AA[i][j] *= f;
|
|
|
|
for (j = 0; j < dim ; j++) {
|
|
if (i == j)
|
|
continue;
|
|
f = AA[j][i];
|
|
AA[j][i] = 0.0;
|
|
for (k = i+1; k <= dim; k++)
|
|
AA[j][k] -= f * AA[i][k];
|
|
}
|
|
}
|
|
return(1);
|
|
}
|
|
|
|
/***
|
|
static int exp_div3(a1, a2, a3, x, p1, p2)
|
|
double x;
|
|
double a1, a2, a3;
|
|
double *p1, *p2;
|
|
{
|
|
*p1 = a1 + x;
|
|
*p2 = - a3 / x;
|
|
|
|
return(1);
|
|
}
|
|
***/
|
|
|
|
/***
|
|
***/
|
|
|
|
static int exp_find_roots(a1, a2, a3, ex1, ex2, ex3)
|
|
double a1, a2, a3;
|
|
double *ex1, *ex2, *ex3;
|
|
{
|
|
double x, t;
|
|
double p, q;
|
|
|
|
q = (a1*a1-3.0*a2) / 9.0;
|
|
p = (2.0*a1*a1*a1-9.0*a1*a2+27.0*a3) / 54.0;
|
|
t = q*q*q - p*p;
|
|
if (t >= 0.0) {
|
|
t = acos((double) p /(q * sqrt(q)));
|
|
x = -2.0*sqrt(q)*cos(t / 3.0) - a1/3.0;
|
|
} else {
|
|
if (p > 0.0) {
|
|
t = pow(sqrt(-t)+p, (double) 1.0 / 3.0);
|
|
x = -(t + q / t) - a1/3.0;
|
|
} else if (p == 0.0) {
|
|
x = -a1/3.0;
|
|
} else {
|
|
t = pow(sqrt(-t)-p, (double) 1.0 / 3.0);
|
|
x = (t + q / t) - a1/3.0;
|
|
}
|
|
}
|
|
{
|
|
double ex1;
|
|
int i = 0;
|
|
ex1 = x;
|
|
for (t = root3(a1, a2, a3, x); ABS(t-x) > 5.0e-4;
|
|
t = root3(a1, a2, a3, x))
|
|
if (++i == 32) {
|
|
x = ex1;
|
|
break;
|
|
} else
|
|
x = t;
|
|
}
|
|
/***
|
|
x = a1;
|
|
for (t = root3(a1, a2, a3, x); ABS(t-x) > epsi2;
|
|
t = root3(a1, a2, a3, x)) {
|
|
x = t;
|
|
i++;
|
|
if (i > 1000) {
|
|
x = 0.5 * (x + root3(a1, a2, a3, x));
|
|
j++;
|
|
if (j == 3)
|
|
break;
|
|
i = 0;
|
|
}
|
|
}
|
|
***/
|
|
*ex1 = x;
|
|
div3(a1, a2, a3, x, &a1, &a2);
|
|
|
|
t = a1 * a1 - 4.0 * a2;
|
|
if (t < 0) {
|
|
ifImg = 1;
|
|
printf("***** Two Imaginary Roots.\n");
|
|
*ex3 = 0.5 * sqrt(-t);
|
|
*ex2 = -0.5 * a1;
|
|
} else {
|
|
ifImg = 0;
|
|
t *= 1.0e-16;
|
|
t = sqrt(t)*1.0e8;
|
|
if (a1 >= 0.0)
|
|
*ex2 = t = -0.5 * (a1 + t);
|
|
else
|
|
*ex2 = t = -0.5 * (a1 - t);
|
|
*ex3 = a2 / t;
|
|
/*
|
|
*ex2 = 0.5 * (-a1 + t);
|
|
*ex3 = 0.5 * (-a1 - t);
|
|
*/
|
|
}
|
|
|
|
return(1);
|
|
}
|
|
static NDnamePt
|
|
insert_ND(name, ndn)
|
|
char *name;
|
|
NDnamePt *ndn;
|
|
{
|
|
int cmp;
|
|
NDnamePt p;
|
|
|
|
if (*ndn == NULL) {
|
|
p = *ndn = (NDnamePt) malloc(sizeof (NDname));
|
|
p->nd = NULL;
|
|
p->right = p->left = NULL;
|
|
strcpy(p->id, name);
|
|
return(p);
|
|
}
|
|
cmp = strcmp((*ndn)->id, name);
|
|
if (cmp == 0)
|
|
return(*ndn);
|
|
else {
|
|
if (cmp < 0)
|
|
return(insert_ND(name, &((*ndn)->left)));
|
|
else
|
|
return(insert_ND(name, &((*ndn)->right)));
|
|
}
|
|
}
|
|
|
|
|
|
static NODE
|
|
*insert_node(name)
|
|
char *name;
|
|
{
|
|
NDnamePt n;
|
|
NODE *p;
|
|
|
|
n = insert_ND(name, &ndn);
|
|
if (n->nd == NULL) {
|
|
p = NEW_node();
|
|
p->name = n;
|
|
n->nd = p;
|
|
p->next = node_tab;
|
|
node_tab = p;
|
|
return(p);
|
|
} else
|
|
return(n->nd);
|
|
}
|
|
|
|
static NODE
|
|
*NEW_node()
|
|
{
|
|
NODE *n;
|
|
|
|
n = (NODE *) malloc (sizeof (NODE));
|
|
n->mptr = NULL;
|
|
n->gptr = NULL;
|
|
n->cptr = NULL;
|
|
n->rptr = NULL;
|
|
n->tptr = NULL;
|
|
n->cplptr = NULL;
|
|
n->rlptr = NULL;
|
|
n->ddptr = NULL;
|
|
n->cvccsptr = NULL;
|
|
n->vccsptr = NULL;
|
|
n->CL = 0.0;
|
|
n->V = n->dv = 0.0;
|
|
n->gsum = n->cgsum = 0;
|
|
n->is = 0;
|
|
n->tag = 0;
|
|
n->flag = 0;
|
|
n->region = NULL;
|
|
n->ofile = NULL;
|
|
n->dvtag = 0;
|
|
|
|
return(n);
|
|
}
|
|
|
|
static int find_roots(a1, a2, a3, x1, x2, x3)
|
|
double a1, a2, a3;
|
|
double *x1, *x2, *x3;
|
|
{
|
|
double x, t;
|
|
double p, q;
|
|
|
|
q = (a1*a1-3.0*a2) / 9.0;
|
|
p = (2.0*a1*a1*a1-9.0*a1*a2+27.0*a3) / 54.0;
|
|
t = q*q*q - p*p;
|
|
if (t >= 0.0) {
|
|
t = acos((double) p /(q * sqrt(q)));
|
|
x = -2.0*sqrt(q)*cos(t / 3.0) - a1/3.0;
|
|
} else {
|
|
if (p > 0.0) {
|
|
t = pow(sqrt(-t)+p, (double) 1.0 / 3.0);
|
|
x = -(t + q / t) - a1/3.0;
|
|
} else if (p == 0.0) {
|
|
x = -a1/3.0;
|
|
} else {
|
|
t = pow(sqrt(-t)-p, (double) 1.0 / 3.0);
|
|
x = (t + q / t) - a1/3.0;
|
|
}
|
|
}
|
|
{
|
|
double x1;
|
|
int i = 0;
|
|
x1 = x;
|
|
for (t = root3(a1, a2, a3, x); ABS(t-x) > 5.0e-4;
|
|
t = root3(a1, a2, a3, x))
|
|
if (++i == 32) {
|
|
x = x1;
|
|
break;
|
|
} else
|
|
x = t;
|
|
}
|
|
/*
|
|
x = a1;
|
|
i = 0;
|
|
j = 0;
|
|
for (t = root3(a1, a2, a3, x); ABS(t-x) > epsi;
|
|
t = root3(a1, a2, a3, x)) {
|
|
x = t;
|
|
i++;
|
|
if (i > 1000) {
|
|
x = 0.5 * (x + root3(a1, a2, a3, x));
|
|
j++;
|
|
if (j == 3)
|
|
break;
|
|
i = 0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
*x1 = x;
|
|
div3(a1, a2, a3, x, &a1, &a2);
|
|
|
|
t = a1 * a1 - 4.0 * a2;
|
|
if (t < 0) {
|
|
printf("***** Two Imaginary Roots in Characteristic Admittance.\n");
|
|
exit(0);
|
|
}
|
|
|
|
t *= 1.0e-18;
|
|
t = sqrt(t) * 1.0e9;
|
|
if (a1 >= 0.0)
|
|
*x2 = t = -0.5 * (a1 + t);
|
|
else
|
|
*x2 = t = -0.5 * (a1 - t);
|
|
*x3 = a2 / t;
|
|
/*
|
|
*x2 = 0.5 * (-a1 + t);
|
|
*x3 = 0.5 * (-a1 - t);
|
|
*/
|
|
return(1);
|
|
}
|
|
|