1 /**********
2 Copyright 1991 Regents of the University of California.  All rights reserved.
3 Author:	1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
4 **********/
5 
6 #include "ngspice/ngspice.h"
7 #include "ngspice/cktdefs.h"
8 #include "ngspice/smpdefs.h"
9 #include "nbjtdefs.h"
10 #include "ngspice/numconst.h"
11 #include "ngspice/numenum.h"
12 #include "ngspice/sperror.h"
13 #include "../../../ciderlib/oned/onedext.h"
14 #include "ngspice/cidersupt.h"
15 #include "ngspice/ciderinp.h"
16 #include "ngspice/suffix.h"
17 #include "ngspice/meshext.h"
18 
19 #define TSCALLOC(var, size, type)\
20 if (size && (var =(type *)calloc(1, (unsigned)(size)*sizeof(type))) == NULL) {\
21    return(E_NOMEM);\
22 }
23 
24 int
NBJTsetup(SMPmatrix * matrix,GENmodel * inModel,CKTcircuit * ckt,int * states)25 NBJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
26 /*
27  * load the diode structure with those pointers needed later for fast matrix
28  * loading
29  */
30 {
31   register NBJTmodel *model = (NBJTmodel *) inModel;
32   register NBJTinstance *inst;
33   METHcard *methods;
34   MODLcard *models;
35   OPTNcard *options;
36   OUTPcard *outputs;
37   int error;
38   int xMeshSize;
39   ONEdevice *pDevice;
40   ONEcoord *xCoordList = NULL;
41   ONEdomain *domainList = NULL;
42   DOPprofile *profileList = NULL;
43   DOPtable *dopTableList = NULL;
44   ONEmaterial *pM, *pMaterial = NULL, *materialList = NULL;
45   double startTime;
46 
47 
48   /* loop through all the diode models */
49   for (; model != NULL; model = NBJTnextModel(model)) {
50     if (!model->NBJTpInfo) {
51       TSCALLOC(model->NBJTpInfo, 1, ONEtranInfo);
52     }
53     methods = model->NBJTmethods;
54     if (!methods) {
55       TSCALLOC(methods, 1, METHcard);
56       model->NBJTmethods = methods;
57     }
58     models = model->NBJTmodels;
59     if (!models) {
60       TSCALLOC(models, 1, MODLcard);
61       model->NBJTmodels = models;
62     }
63     options = model->NBJToptions;
64     if (!options) {
65       TSCALLOC(options, 1, OPTNcard);
66       model->NBJToptions = options;
67     }
68     outputs = model->NBJToutputs;
69     if (!outputs) {
70       TSCALLOC(outputs, 1, OUTPcard);
71       model->NBJToutputs = outputs;
72     }
73     if (!methods->METHvoltPredGiven) {
74       methods->METHvoltPred = FALSE;
75     }
76     if (!methods->METHmobDerivGiven) {
77       methods->METHmobDeriv = TRUE;
78     }
79     if (!methods->METHoneCarrierGiven) {
80       methods->METHoneCarrier = FALSE;
81     }
82     if (!methods->METHacAnalysisMethodGiven) {
83       methods->METHacAnalysisMethod = SOR;
84     }
85     if (!methods->METHdabstolGiven) {
86       methods->METHdabstol = DABSTOL1D;
87     }
88     if (!methods->METHdreltolGiven) {
89       methods->METHdreltol = ckt->CKTreltol;
90     }
91     if (!methods->METHitLimGiven) {
92       methods->METHitLim = 20;
93     }
94     if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
95       methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
96     }
97     if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
98       options->OPTNdefa = 1.0e4 /* cm^2 */ ;
99     }
100     if (!options->OPTNbaseLengthGiven) {
101       options->OPTNbaseLength = 0.0;
102     }
103     if (!options->OPTNbaseAreaGiven) {
104       options->OPTNbaseArea = 1.0;
105     }
106     if (!options->OPTNdeviceTypeGiven) {
107       options->OPTNdeviceType = OPTN_BIPOLAR;
108     }
109     if (!options->OPTNicFileGiven) {
110       options->OPTNicFile = NULL;
111       options->OPTNunique = FALSE;		/* Can't form a unique name. */
112     }
113     if (!options->OPTNuniqueGiven) {
114       options->OPTNunique = FALSE;
115     }
116 
117     /* Set up the rest of the card lists */
118     if ((error = MODLsetup(model->NBJTmodels)) != 0)
119       return (error);
120     BandGapNarrowing = models->MODLbandGapNarrowing;
121     ConcDepLifetime = models->MODLconcDepLifetime;
122     TempDepMobility = models->MODLtempDepMobility;
123     ConcDepMobility = models->MODLconcDepMobility;
124 
125     if ((error = OUTPsetup(model->NBJToutputs)) != 0)
126       return (error);
127     if ((error = MATLsetup(model->NBJTmaterials, &materialList)) != 0)
128       return (error);
129     if ((error = MOBsetup(model->NBJTmobility, materialList)) != 0)
130       return (error);
131     if ((error = MESHsetup('x', model->NBJTxMeshes, &xCoordList, &xMeshSize)) != 0)
132       return (error);
133     if ((error = DOMNsetup(model->NBJTdomains, &domainList,
134 	    xCoordList, NULL, materialList)) != 0)
135       return (error);
136     if ((error = BDRYsetup(model->NBJTboundaries,
137 	    xCoordList, NULL, domainList)) != 0)
138       return (error);
139     if ((error = CONTsetup(model->NBJTcontacts, NULL)) != 0)
140       return (error);
141     if ((error = DOPsetup(model->NBJTdopings, &profileList,
142 	    &dopTableList, xCoordList, NULL)) != 0)
143       return (error);
144     model->NBJTmatlInfo = materialList;
145     model->NBJTprofiles = profileList;
146     model->NBJTdopTables = dopTableList;
147 
148     /* loop through all the instances of the model */
149     for (inst = NBJTinstances(model); inst != NULL;
150          inst = NBJTnextInstance(inst)) {
151 
152       startTime = SPfrontEnd->IFseconds();
153 
154       if (!inst->NBJTprintGiven) {
155 	inst->NBJTprint = 0;
156       } else if (inst->NBJTprint <= 0) {
157 	inst->NBJTprint = 1;
158       }
159       if (!inst->NBJTicFileGiven) {
160 	if (options->OPTNunique) {
161 	  inst->NBJTicFile = tprintf("%s.%s", options->OPTNicFile, inst->NBJTname);
162 	} else if (options->OPTNicFile != NULL) {
163 	  inst->NBJTicFile = tprintf("%s", options->OPTNicFile);
164 	} else {
165 	  inst->NBJTicFile = NULL;
166 	}
167       }
168       inst->NBJTstate = *states;
169       *states += NBJTnumStates;
170 
171       if (!inst->NBJTpDevice) {
172 	/* Assign the mesh info to each instance. */
173 	TSCALLOC(pDevice, 1, ONEdevice);
174 	TSCALLOC(pDevice->pStats, 1, ONEstats);
175 	pDevice->name = inst->NBJTname;
176 	pDevice->solverType = SLV_NONE;
177 	pDevice->numNodes = xMeshSize;
178 	pDevice->abstol = methods->METHdabstol;
179 	pDevice->reltol = methods->METHdreltol;
180 	pDevice->rhsImag = NULL;
181 	TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *);
182 
183 	/* Create a copy of material data that can change with temperature. */
184 	pDevice->pMaterials = NULL;
185 	for (pM = materialList; pM != NULL; pM = pM->next) {
186 	  if (pDevice->pMaterials == NULL) {
187 	    TSCALLOC(pMaterial, 1, ONEmaterial);
188 	    pDevice->pMaterials = pMaterial;
189 	  } else {
190 	    TSCALLOC(pMaterial->next, 1, ONEmaterial);
191 	    pMaterial = pMaterial->next;
192 	  }
193 	  /* Copy everything, then fix the incorrect pointer. */
194 	  memcpy(pMaterial, pM, sizeof(ONEmaterial));
195 	  pMaterial->next = NULL;
196 	}
197 
198 	/* generate the mesh structure for the device */
199 	ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials);
200 
201 	if (options->OPTNbaseDepthGiven) {
202 	  /* The base contact depth has been specified in the input. */
203 	  pDevice->baseIndex = MESHlocate(xCoordList, options->OPTNbaseDepth);
204 	} else {
205 	  pDevice->baseIndex = -1;	/* Invalid index acts as a flag */
206 	}
207 	/* store the device info in the instance */
208 	inst->NBJTpDevice = pDevice;
209       }
210       /* Now update the state pointers. */
211       ONEgetStatePointers(inst->NBJTpDevice, states);
212 
213       /* Wipe out statistics from previous runs (if any). */
214       memset(inst->NBJTpDevice->pStats, 0, sizeof(ONEstats));
215 
216       inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] +=
217 	  SPfrontEnd->IFseconds() - startTime;
218 
219       /* macro to make elements with built in test for out of memory */
220 #define TSTALLOC(ptr,first,second) \
221 do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\
222   return(E_NOMEM);\
223 } } while(0)
224 
225       TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode);
226       TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode);
227       TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode);
228       TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode);
229       TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode);
230       TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode);
231       TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode);
232       TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode);
233       TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode);
234     }
235     /* Clean up lists */
236     killCoordInfo(xCoordList);
237     killDomainInfo(domainList);
238   }
239   return (OK);
240 }
241