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