1 /**********
2 Copyright 1992 Regents of the University of California. All rights reserved.
3 Author: 1992 David A. Gates, U. C. Berkeley CAD Group
4 **********/
5
6 /*
7 * Functions needed to read solutions for 2D devices.
8 */
9
10 #include "ngspice/ngspice.h"
11 #include "ngspice/plot.h"
12 #include "ngspice/numglobs.h"
13 #include "ngspice/numenum.h"
14 #include "ngspice/twodev.h"
15 #include "ngspice/twomesh.h"
16 #include "twoddefs.h"
17 #include "twodext.h"
18 #include "ngspice/cidersupt.h"
19
20
21 int
TWOreadState(TWOdevice * pDevice,char * fileName,int numVolts,double * pV1,double * pV2,double * pV3)22 TWOreadState(TWOdevice *pDevice, char *fileName, int numVolts, double *pV1,
23 double *pV2, double *pV3)
24 /* char *fileName: File containing raw data */
25 /* int numVolts: Number of voltage differences */
26 /* double *pV1, *pV2, *pV3: Pointer to return them in */
27 {
28 int dataLength;
29 int i, index, xIndex, yIndex;
30 TWOnode ***nodeArray = NULL;
31 TWOnode *pNode;
32 TWOelem *pElem;
33 double refPsi = 0.0;
34 double *psiData, *nData, *pData;
35 double *vData[3];
36 struct plot *stateDB;
37 struct plot *voltsDB;
38 char voltName[80];
39
40 stateDB = DBread( fileName );
41 if (stateDB == NULL) return (-1);
42 voltsDB = stateDB->pl_next;
43 if (voltsDB == NULL) return (-1);
44
45 for (i=0; i < numVolts; i++ ) {
46 sprintf( voltName, "v%d%d", i+1, numVolts+1 );
47 vData[i] = DBgetData( voltsDB, voltName, 1 );
48 if (vData[i] == NULL) return (-1);
49 }
50 dataLength = pDevice->numXNodes * pDevice->numYNodes;
51 psiData = DBgetData( stateDB, "psi", dataLength );
52 nData = DBgetData( stateDB, "n", dataLength );
53 pData = DBgetData( stateDB, "p", dataLength );
54 if (psiData == NULL || nData == NULL || pData == NULL) return (-1);
55
56 if (pV1 != NULL) {
57 *pV1 = vData[0][0];
58 FREE( vData[0] );
59 }
60 if (pV2 != NULL) {
61 *pV2 = vData[1][0];
62 FREE( vData[1] );
63 }
64 if (pV3 != NULL) {
65 *pV3 = vData[2][0];
66 FREE( vData[2] );
67 }
68
69 /* generate the work array for copying node info */
70 XCALLOC(nodeArray, TWOnode **, 1 + pDevice->numXNodes);
71 for (xIndex = 1; xIndex <= pDevice->numXNodes; xIndex++) {
72 XCALLOC(nodeArray[xIndex], TWOnode *, 1 + pDevice->numYNodes);
73 }
74
75 /* store the nodes in this work array and use later */
76 for (xIndex = 1; xIndex < pDevice->numXNodes; xIndex++) {
77 for (yIndex = 1; yIndex < pDevice->numYNodes; yIndex++) {
78 pElem = pDevice->elemArray[xIndex][yIndex];
79 if (pElem != NULL) {
80 if (refPsi == 0.0 && pElem->matlInfo->type == SEMICON) {
81 refPsi = pElem->matlInfo->refPsi;
82 }
83 for (index = 0; index <= 3; index++) {
84 if (pElem->evalNodes[index]) {
85 pNode = pElem->pNodes[index];
86 nodeArray[pNode->nodeI][pNode->nodeJ] = pNode;
87 }
88 }
89 }
90 }
91 }
92 index = 0;
93 for (xIndex = 1; xIndex <= pDevice->numXNodes; xIndex++) {
94 for (yIndex = 1; yIndex <= pDevice->numYNodes; yIndex++) {
95 pNode = nodeArray[xIndex][yIndex];
96 index++;
97 if (pNode != NULL) {
98 pNode->psi = psiData[index-1]/VNorm + refPsi;
99 pNode->nConc = nData[index-1]/NNorm;
100 pNode->pConc = pData[index-1]/NNorm;
101 }
102 }
103 }
104 /* Delete work array. */
105 for (xIndex = 1; xIndex <= pDevice->numXNodes; xIndex++) {
106 FREE(nodeArray[xIndex]);
107 }
108 FREE(nodeArray);
109
110 FREE(psiData);
111 FREE(nData);
112 FREE(pData);
113
114 return (0);
115 }
116