1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 **********/
4 
5 #include "ngspice/ngspice.h"
6 #include "ngspice/complex.h"
7 #include "ngspice/cktdefs.h"
8 #include "ngspice/smpdefs.h"
9 #include "ngspice/pzdefs.h"
10 #include "ngspice/trandefs.h"   /* only to get the 'mode' definitions */
11 #include "ngspice/sperror.h"
12 
13 
14 #define DEBUG	if (0)
15 
16 /* ARGSUSED */
17 int
PZan(CKTcircuit * ckt,int reset)18 PZan(CKTcircuit *ckt, int reset)
19 {
20     PZAN *job = (PZAN *) ckt->CKTcurJob;
21 
22     int error;
23     int numNames;
24     IFuid *nameList;
25     runDesc *plot = NULL;
26 
27     NG_IGNORE(reset);
28 
29     error = PZinit(ckt);
30     if (error != OK) return error;
31 
32     /* Calculate small signal parameters at the operating point */
33     error = CKTop(ckt, (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITJCT,
34             (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITFLOAT,
35             ckt->CKTdcMaxIter);
36     if (error)
37 	return(error);
38 
39     ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCOP | MODEINITSMSIG;
40     error = CKTload(ckt); /* Make sure that all small signal params are
41 			       * set */
42     if (error)
43 	return(error);
44 
45     if (ckt->CKTkeepOpInfo) {
46 	/* Dump operating point. */
47 	error = CKTnames(ckt,&numNames,&nameList);
48 	if(error) return(error);
49         error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
50                                            "Distortion Operating Point",
51                                            NULL, IF_REAL,
52                                            numNames, nameList, IF_REAL,
53                                            &plot);
54 	if(error) return(error);
55 	CKTdump(ckt, 0.0, plot);
56 	SPfrontEnd->OUTendPlot (plot);
57     }
58 
59     if (job->PZwhich & PZ_DO_POLES) {
60 	error = CKTpzSetup(ckt, PZ_DO_POLES);
61 	if (error != OK)
62 	    return error;
63         error = CKTpzFindZeros(ckt, &job->PZpoleList, &job->PZnPoles);
64         if (error != OK)
65 	    return(error);
66     }
67 
68     if (job->PZwhich & PZ_DO_ZEROS) {
69 	error = CKTpzSetup(ckt, PZ_DO_ZEROS);
70 	if (error != OK)
71 	    return error;
72         error = CKTpzFindZeros(ckt, &job->PZzeroList, &job->PZnZeros);
73         if (error != OK)
74 	    return(error);
75     }
76 
77     return PZpost(ckt);
78 }
79 
80 /*
81  * Perform error checking
82  */
83 
84 int
PZinit(CKTcircuit * ckt)85 PZinit(CKTcircuit *ckt)
86 {
87     PZAN *job = (PZAN *) ckt->CKTcurJob;
88     int	i;
89 
90     i = CKTtypelook("transmission line");
91     if (i == -1) {
92 	    i = CKTtypelook("Tranline");
93 	    if (i == -1)
94 		i = CKTtypelook("LTRA");
95     }
96     if (i != -1 && ckt->CKThead[i] != NULL)
97 	MERROR(E_XMISSIONLINE, "Transmission lines not supported");
98 
99     job->PZpoleList = NULL;
100     job->PZzeroList = NULL;
101     job->PZnPoles = 0;
102     job->PZnZeros = 0;
103 
104     if (job->PZin_pos == job->PZin_neg)
105 	MERROR(E_SHORT, "Input is shorted");
106 
107     if (job->PZout_pos == job->PZout_neg)
108 	MERROR(E_SHORT, "Output is shorted");
109 
110     if (job->PZin_pos == job->PZout_pos
111         && job->PZin_neg == job->PZout_neg
112 	&& job->PZinput_type == PZ_IN_VOL)
113 	MERROR(E_INISOUT, "Transfer function is unity");
114     else if (job->PZin_pos == job->PZout_neg
115         && job->PZin_neg == job->PZout_pos
116 	&& job->PZinput_type == PZ_IN_VOL)
117 	MERROR(E_INISOUT, "Transfer function is -1");
118 
119     return(OK);
120 }
121 
122 /*
123  * PZpost  Post-processing of the pole-zero analysis results
124  */
125 
126 int
PZpost(CKTcircuit * ckt)127 PZpost(CKTcircuit *ckt)
128 {
129     PZAN	*job = (PZAN *) ckt->CKTcurJob;
130     runDesc	*pzPlotPtr = NULL; /* the plot pointer for front end */
131     IFcomplex	*out_list;
132     IFvalue	outData;    /* output variable (points to out_list) */
133     IFuid	*namelist;
134     PZtrial	*root;
135     char	name[50];
136     int		i, j;
137 
138     namelist = TMALLOC(IFuid, job->PZnPoles + job->PZnZeros);
139     out_list = TMALLOC(IFcomplex, job->PZnPoles + job->PZnZeros);
140 
141     j = 0;
142     for (i = 0; i < job->PZnPoles; i++) {
143 	sprintf(name, "pole(%-u)", i+1);
144 	SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, name, UID_OTHER, NULL);
145     }
146     for (i = 0; i < job->PZnZeros; i++) {
147 	sprintf(name, "zero(%-u)", i+1);
148 	SPfrontEnd->IFnewUid (ckt, &(namelist[j++]), NULL, name, UID_OTHER, NULL);
149     }
150 
151     SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
152                                ckt->CKTcurJob->JOBname,
153                                NULL, 0,
154                                job->PZnPoles + job->PZnZeros, namelist, IF_COMPLEX,
155                                &pzPlotPtr);
156 
157     j = 0;
158     if (job->PZnPoles > 0) {
159 	for (root = job->PZpoleList; root != NULL; root = root->next) {
160 	    for (i = 0; i < root->multiplicity; i++) {
161 		out_list[j].real = root->s.real;
162 		out_list[j].imag = root->s.imag;
163 		j += 1;
164 		if (root->s.imag != 0.0) {
165 		    out_list[j].real = root->s.real;
166 		    out_list[j].imag = -root->s.imag;
167 		    j += 1;
168 		}
169 	    }
170 	    DEBUG printf("LIST pole: (%g,%g) x %d\n",
171 		root->s.real, root->s.imag, root->multiplicity);
172 	}
173     }
174 
175     if (job->PZnZeros > 0) {
176 	for (root = job->PZzeroList; root != NULL; root = root->next) {
177 	    for (i = 0; i < root->multiplicity; i++) {
178 		out_list[j].real = root->s.real;
179 		out_list[j].imag = root->s.imag;
180 		j += 1;
181 		if (root->s.imag != 0.0) {
182 		    out_list[j].real = root->s.real;
183 		    out_list[j].imag = -root->s.imag;
184 		    j += 1;
185 		}
186 	    }
187 	    DEBUG printf("LIST zero: (%g,%g) x %d\n",
188 		root->s.real, root->s.imag, root->multiplicity);
189 	}
190     }
191 
192     outData.v.numValue = job->PZnPoles + job->PZnZeros;
193     outData.v.vec.cVec = out_list;
194 
195     SPfrontEnd->OUTpData (pzPlotPtr, NULL, &outData);
196     SPfrontEnd->OUTendPlot (pzPlotPtr);
197 
198     return(OK);
199 }
200