1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Thomas L. Quarles
4 
5 This function is obsolete (was used by an old sensitivity analysis)
6 **********/
7 
8 /* actually load the current sensitivity
9  * information into the  array previously provided
10  */
11 
12 #include "ngspice/ngspice.h"
13 #include "ngspice/cktdefs.h"
14 #include "ngspice/smpdefs.h"
15 #include "bjtdefs.h"
16 #include "ngspice/const.h"
17 #include "ngspice/sperror.h"
18 #include "ngspice/ifsim.h"
19 #include "ngspice/suffix.h"
20 
21 
22 int
BJTsLoad(GENmodel * inModel,CKTcircuit * ckt)23 BJTsLoad(GENmodel *inModel, CKTcircuit *ckt)
24 {
25     BJTmodel *model = (BJTmodel*)inModel;
26     BJTinstance *here;
27     double   SaveState0[27];
28     int    i;
29     int    iparmno;
30     int    error;
31     double A0;
32     double DELA;
33     double Apert;
34     double DELAinv;
35     double cb0;
36     double cb;
37     double cc0;
38     double cc;
39     double cx0;
40     double ccpr0;
41     double cepr0;
42     double DcbDp;
43     double DccDp;
44     double DceDp;
45     double DccprDp;
46     double DceprDp;
47     double DcxDp;
48     double DbprmDp;
49     double DcprmDp;
50     double DeprmDp;
51     double gx;
52     double gx0;
53     double tag0;
54     double tag1;
55     double qbe0;
56     double qbe;
57     double qbc0;
58     double qbc;
59     double qcs0;
60     double qcs;
61     double qbx0;
62     double qbx;
63     double DqbeDp = 0.0;
64     double DqbcDp = 0.0;
65     double DqcsDp = 0.0;
66     double DqbxDp = 0.0;
67     double Osxpbe;
68     double Osxpbc;
69     double Osxpcs;
70     double Osxpbx;
71     SENstruct *info;
72 
73     tag0 = ckt->CKTag[0];
74     tag1 = ckt->CKTag[1];
75     if(ckt->CKTorder == 1){
76         tag1 = 0;
77     }
78 #ifdef SENSDEBUG
79     printf("BJTsenload \n");
80     printf("CKTtime = %.5e\n",ckt->CKTtime);
81     printf("CKTorder = %.5e\n",ckt->CKTorder);
82     printf("tag0=%.7e,tag1=%.7e\n",tag0,tag1);
83 #endif /* SENSDEBUG */
84     info = ckt->CKTsenInfo;
85 
86     info->SENstatus = PERTURBATION;
87 
88     /*  loop through all the models */
89     for( ; model != NULL; model = BJTnextModel(model)) {
90 
91         /* loop through all the instances of the model */
92         for (here = BJTinstances(model); here != NULL ;
93                 here=BJTnextInstance(here)) {
94 
95 #ifdef SENSDEBUG
96             printf("base = %d , baseprm = %d ,col = %d, colprm = %d\n",
97                     here->BJTbaseNode ,here->BJTbasePrimeNode,
98                     here->BJTcolNode,here->BJTcolPrimeNode);
99             printf("emit = %d , emitprm = %d ,subst = %d, senparmno = %d\n",
100                     here->BJTemitNode ,here->BJTemitPrimeNode,
101                     here->BJTsubstNode,here->BJTsenParmNo);
102 #endif /* SENSDEBUG */
103 
104 
105             /* save the unperturbed values in the state vector */
106             for(i=0; i <= 20; i++){
107                 *(SaveState0 + i) = *(ckt->CKTstate0 + here->BJTstate + i);
108             }
109             *(SaveState0 + 21) = *(ckt->CKTstate1 + here->BJTcexbc);
110             *(SaveState0 + 22) = *(ckt->CKTstate2 + here->BJTcexbc);
111             *(SaveState0 + 23) = here->BJTcapbe;
112             *(SaveState0 + 24) = here->BJTcapbc;
113             *(SaveState0 + 25) = here->BJTcapsub;
114             *(SaveState0 + 26) = here->BJTcapbx;
115 
116             if(here->BJTsenParmNo == 0) goto next;
117 
118             cx0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
119             ccpr0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
120             cepr0 = -cx0 - ccpr0;
121 
122             here->BJTsenPertFlag = ON;
123             error =  BJTload((GENmodel*)model,ckt);
124             if(error) return(error);
125 
126             cb0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
127             cc0 = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
128             gx0 = *(ckt->CKTstate0 + here->BJTgx);
129 
130             qbe0 = *(ckt->CKTstate0 + here->BJTqbe);
131             qbc0 = *(ckt->CKTstate0 + here->BJTqbc);
132             qcs0 = *(ckt->CKTstate0 + here->BJTqsub);
133             qbx0 = *(ckt->CKTstate0 + here->BJTqbx);
134 
135             /* perturbation of area */
136 
137             A0 = here->BJTarea;
138             DELA = info->SENpertfac * A0;
139             Apert = A0 + DELA;
140             DELAinv = 1.0/DELA;
141             here->BJTsenPertFlag = ON;
142             here->BJTarea = Apert;
143             error =  BJTload((GENmodel*)model,ckt);
144             if(error) return(error);
145             here->BJTarea = A0;
146             here->BJTsenPertFlag = OFF;
147 
148 
149             cb = model->BJTtype * *(ckt->CKTstate0 + here->BJTcb);
150             cc = model->BJTtype * *(ckt->CKTstate0 + here->BJTcc);
151             gx = *(ckt->CKTstate0 + here->BJTgx);
152 
153             qbe = *(ckt->CKTstate0 + here->BJTqbe);
154             qbc = *(ckt->CKTstate0 + here->BJTqbc);
155             qcs = *(ckt->CKTstate0 + here->BJTqsub);
156             qbx = *(ckt->CKTstate0 + here->BJTqbx);
157 
158             /* compute the gradients of currents */
159             DcbDp = (cb - cb0) * DELAinv;
160             DccDp = (cc - cc0) * DELAinv;
161             DceDp = DcbDp + DccDp;
162 
163             DccprDp  = 0;
164             DceprDp  = 0;
165             DcxDp  = 0;
166             if(here->BJTcolNode != here->BJTcolPrimeNode)
167                 DccprDp = ccpr0 * info->SENpertfac * DELAinv;
168             if(here->BJTemitNode != here->BJTemitPrimeNode)
169                 DceprDp = cepr0 * info->SENpertfac * DELAinv;
170             if(here->BJTbaseNode != here->BJTbasePrimeNode){
171                 if(gx0) DcxDp =  cx0 * DELAinv * (gx-gx0)/gx0;
172             }
173             DbprmDp = DcbDp - DcxDp;
174             DcprmDp = DccDp - DccprDp;
175             DeprmDp = - DceDp  - DceprDp;
176 
177             DqbeDp = (qbe - qbe0)*DELAinv;
178             DqbcDp = (qbc - qbc0)*DELAinv;
179             DqcsDp = (qcs - qcs0)*DELAinv;
180             DqbxDp = (qbx - qbx0)*DELAinv;
181 
182             *(here->BJTdphibedp) = DqbeDp;
183             *(here->BJTdphibcdp) = DqbcDp;
184             *(here->BJTdphisubdp) = DqcsDp;
185             *(here->BJTdphibxdp) = DqbxDp;
186 
187 #ifdef SENSDEBUG
188             printf("cb0 = %.7e ,cb = %.7e,\n",cb0,cb);
189             printf("cc0 = %.7e ,cc = %.7e,\n",cc0,cc);
190             printf("ccpr0 = %.7e \n",ccpr0);
191             printf("cepr0 = %.7e \n",cepr0);
192             printf("cx0 = %.7e \n",cx0);
193             printf("qbe0 = %.7e ,qbe = %.7e,\n",qbe0,qbe);
194             printf("qbc0 = %.7e ,qbc = %.7e,\n",qbc0,qbc);
195             printf("qcs0 = %.7e ,qcs = %.7e,\n",qcs0,qcs);
196             printf("qbx0 = %.7e ,qbx = %.7e,\n",qbx0,qbx);
197             printf("\n");
198 
199 #endif /* SENSDEBUG */
200 
201             if((info->SENmode == TRANSEN) &&
202                 (ckt->CKTmode & MODEINITTRAN))
203                 goto restore;
204 
205             /* load the RHS matrix */
206 
207             *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo)
208                 -= DcxDp;
209             *(info->SEN_RHS[here->BJTbasePrimeNode] + here->BJTsenParmNo)
210                 -= DbprmDp;
211             *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo)
212                 -= DccprDp;
213             *(info->SEN_RHS[here->BJTcolPrimeNode] + here->BJTsenParmNo)
214                 -= DcprmDp;
215             *(info->SEN_RHS[here->BJTemitNode] + here->BJTsenParmNo)
216                 -= DceprDp;
217             *(info->SEN_RHS[here->BJTemitPrimeNode] + here->BJTsenParmNo)
218                 -= DeprmDp;
219 #ifdef SENSDEBUG
220             printf("after loading\n");
221             printf("DcxDp=%.7e\n",
222                     *(info->SEN_RHS[here->BJTbaseNode] + here->BJTsenParmNo));
223             printf("DcbprmDp=%.7e\n",
224                     *(info->SEN_RHS[here->BJTbasePrimeNode] +
225                     here->BJTsenParmNo));
226             printf("DccprDp=%.7e\n",
227                     *(info->SEN_RHS[here->BJTcolNode] + here->BJTsenParmNo));
228             printf("DcprmDp=%.7e\n",
229                     *(info->SEN_RHS[here->BJTcolPrimeNode] +
230                     here->BJTsenParmNo));
231             printf("DceprDp=%.7e\n",
232                     *(info->SEN_RHS[here->BJTemitNode] +
233                     here->BJTsenParmNo));
234             printf("DceprmDp=%.7e\n",
235                     *(info->SEN_RHS[here->BJTemitPrimeNode] +
236                     here->BJTsenParmNo));
237 #endif /* SENSDEBUG */
238 
239 next:
240             if((info->SENmode == DCSEN)||(ckt->CKTmode&MODETRANOP))goto restore;
241             if((info->SENmode == TRANSEN) &&
242                 (ckt->CKTmode & MODEINITTRAN))
243                 goto restore;
244 
245             for(iparmno = 1;iparmno<=info->SENparms;iparmno++){
246                 Osxpbe = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbe +
247                         8*(iparmno - 1))
248                     + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbe +
249                         8*(iparmno - 1) + 1);
250 
251                 Osxpbc = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbc +
252                         8*(iparmno - 1))
253                     + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbc +
254                         8*(iparmno - 1) + 1);
255 
256                 Osxpcs = tag0 * *(ckt->CKTstate1 + here->BJTsensxpsub +
257                         8*(iparmno - 1))
258                     + tag1 * *(ckt->CKTstate1 + here->BJTsensxpsub +
259                         8*(iparmno - 1) + 1);
260 
261                 Osxpbx = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbx +
262                         8*(iparmno - 1))
263                     + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbx +
264                         8*(iparmno - 1) + 1);
265 #ifdef SENSDEBUG
266                 printf("iparmno=%d\n",iparmno);
267                 printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
268                 printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
269                 printf("sxpbe=%.7e,sdbe=%.7e\n",
270                         *(ckt->CKTstate1 + here->BJTsensxpbe + 8*(iparmno - 1))
271                         ,*(ckt->CKTstate1 + here->BJTsensxpbe +
272                         8*(iparmno - 1) + 1));
273                 printf("sxpbc=%.7e,sdbc=%.7e\n",
274                         *(ckt->CKTstate1 + here->BJTsensxpbc + 8*(iparmno - 1))
275                         ,*(ckt->CKTstate1 + here->BJTsensxpbc +
276                         8*(iparmno - 1) + 1));
277                 printf("\n");
278 #endif /* SENSDEBUG */
279 
280                 if(iparmno == here->BJTsenParmNo){
281                     Osxpbe = Osxpbe -  tag0 * DqbeDp;
282                     Osxpbc = Osxpbc -  tag0 * DqbcDp;
283                     Osxpcs = Osxpcs -  tag0 * DqcsDp;
284                     Osxpbx = Osxpbx -  tag0 * DqbxDp;
285                 }
286 
287 #ifdef SENSDEBUG
288 
289                 printf("Osxpbe=%.7e,Osxpbc=%.7e\n",Osxpbe,Osxpbc);
290                 printf("Osxpcs=%.7e,Osxpbx=%.7e\n",Osxpcs,Osxpbx);
291 #endif /* SENSDEBUG */
292 
293                 *(info->SEN_RHS[here->BJTbaseNode] + iparmno)
294                     += model->BJTtype * Osxpbx;
295 
296                 *(info->SEN_RHS[here->BJTbasePrimeNode] + iparmno)
297                     += model->BJTtype * (Osxpbe + Osxpbc);
298 
299                 *(info->SEN_RHS[here->BJTcolPrimeNode] + iparmno)
300                     -= model->BJTtype * (Osxpbc + Osxpcs + Osxpbx );
301 
302                 *(info->SEN_RHS[here->BJTemitPrimeNode] + iparmno)
303                     -= model->BJTtype * Osxpbe;
304 
305                 *(info->SEN_RHS[here->BJTsubstNode] + iparmno)
306                     += model->BJTtype * Osxpcs;
307 
308             }
309 
310 
311             /* put the unperturbed values back into the state vector */
312 restore:
313             for(i=0; i <= 20; i++){
314                 *(ckt->CKTstate0 + here->BJTstate + i) = *(SaveState0 + i);
315             }
316             *(ckt->CKTstate1 + here->BJTcexbc) = *(SaveState0 + 21);
317             here->BJTcapbe = *(SaveState0 + 23) ;
318             here->BJTcapbc = *(SaveState0 + 24) ;
319             here->BJTcapsub = *(SaveState0 + 25) ;
320             here->BJTcapbx = *(SaveState0 + 26) ;
321 
322         }
323     }
324     info->SENstatus = NORMAL;
325 #ifdef SENSDEBUG
326     printf("BJTsenload end\n");
327 #endif /* SENSDEBUG */
328     return(OK);
329 }
330