You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

180 lines
5.1 KiB

/**********
Copyright 1991 Regents of the University of California. All rights reserved.
Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
Author: 1991 David A. Gates, U. C. Berkeley CAD Group
**********/
#include "ngspice.h"
#include "numglobs.h"
#include "numconst.h"
#include "numenum.h"
#include "twomesh.h"
#include "twodev.h"
#include "bool.h"
#include "twoddefs.h"
#include "twodext.h"
/* Use list-sorting header file to create electrode sorter */
#define TYPE TWOelectrode
#define NEXT next
#define SORT TWOssortElectrodes
#define SORT1 TWOsortElectrodes
#include "lsort.h"
#define ARG_MIN(a,b,c) ((a) > (b) ? 1 : ((a) < (b) ? -1 : (c)))
int
TWOcmpElectrode(TWOelectrode *a, TWOelectrode *b)
{
return ARG_MIN(a->id, b->id, 0);
}
/*
* checkElectrodes
* debug list of electrodes for errors, exit on any error:
* 1. list doesn't have only contiguous id's from 1 to idHigh
* 2. electrodes with box shapes
* 3. order of node numbers is correct
*/
void
checkElectrodes(TWOelectrode *pElectrode, int idHigh)
{
TWOelectrode *pE;
int id;
BOOLEAN error = FALSE;
/*
* order the electrodes
* assign electrode numbers to uninitialized electrodes ( id == -1 )
* uninit electrodes are in reverse order from order in input file
* resort electrodes
*/
pElectrode = TWOsortElectrodes( pElectrode, TWOcmpElectrode );
id = 1;
for (pE = pElectrode; pE != NIL(TWOelectrode); pE = pE->next) {
if (pE->id == -1) pE->id = id++;
}
pElectrode = TWOsortElectrodes( pElectrode, TWOcmpElectrode );
for (pE = pElectrode, id = 1; pE != NIL(TWOelectrode); pE = pE->next) {
/* Check id's */
if ( pE->id < 1 || pE->id > idHigh) {
fprintf(stderr, "Error: electrode %d out of range\n",pE->id);
error = TRUE;
} else if ( pE->id != id ) {
if ( pE->id != ++id ) {
fprintf(stderr, "Error: electrode(s) %d to %d missing\n",id,pE->id-1);
id = pE->id;
error = TRUE;
}
}
}
/* Make sure total number of distinct electrodes is correct */
if ( id != idHigh ) {
fprintf(stderr, "Error: %d electrode%s not equal to %d required\n",
id, (id != 1) ? "s are" : " is", idHigh);
error = TRUE;
}
if (error) {
exit(-1);
}
}
/*
* setupContacts
* go through each set of electrode segments, find its size and find nodes
*/
void
setupContacts(TWOdevice *pDevice, TWOelectrode *pElectrode,
TWOnode ***nodeArray)
{
TWOelectrode *pE;
TWOcontact *pNew = NULL, *pTail;
TWOnode *pNode;
int xIndex, yIndex, nIndex = 0;
int id = 0, electrodeSize[MAXTERMINALS], electrodeType;
int error = FALSE;
/* INITIALIZATION
* 0. Assume ELCT_ID's are initialized to 0 before setup is called
* 1. Add a node only once to only one electrode
* 2. Compute number of nodes in each electrode
* 3. Overwrite SEMICON or INSULATOR nodeType at electrodes
*/
for ( pE = pElectrode; pE != NIL(TWOelectrode); pE = pE->next ) {
if (pE->id != id) { /* Found the next electrode */
id = pE->id;
electrodeSize[id] = 0;
electrodeType = 0;
}
for ( xIndex = pE->ixLo; xIndex <= pE->ixHi; xIndex++ ) {
for ( yIndex = pE->iyLo; yIndex <= pE->iyHi; yIndex++ ) {
pNode = nodeArray[ xIndex ][ yIndex ];
if ( pNode != NIL( TWOnode ) ) {
pNode->nodeType = CONTACT;
/* Assign each node to an electrode only once */
if (pNode->ELCT_ID == 0) { /* Is this a new node? */
pNode->ELCT_ID = id; /* Mark electrode ownership */
electrodeSize[id]++; /* Increase electrode size */
} else if (pNode->ELCT_ID != id) {
/* Node already owned by another electrode */
fprintf(stderr, "Error: electrodes %d and %d overlap at (%d,%d)\n",
pNode->ELCT_ID, id, xIndex, yIndex);
error = TRUE;
}
}
}
}
}
if (error) {
exit(-1);
}
/* ALLOCATION AND NODE GRABBING
* 1. For each electrode, create a new contact structure for the electrode.
* 2. Fill in entries of contact structure
* 3. Update First and Last Contact pointers of device
*/
/*
printElectrodes( pDevice->pFirstContact );
*/
id = 0;
pDevice->pFirstContact = pTail = NIL(TWOcontact);
for ( pE = pElectrode; pE != NIL(TWOelectrode); pE = pE->next ) {
if (pE->id != id) { /* Found the next electrode */
if ( pDevice->pFirstContact == NIL(TWOcontact) ) {
XCALLOC( pNew, TWOcontact, 1 );
pDevice->pFirstContact = pTail = pNew;
} else {
XCALLOC( pNew->next, TWOcontact, 1 );
pTail = pNew = pNew->next;
}
pNew->next = NIL(TWOcontact);
id = pNew->id = pE->id;
pNew->workf = pE->workf;
pNew->numNodes = electrodeSize[id];
nIndex = 0;
XCALLOC( pNew->pNodes, TWOnode *, electrodeSize[id] );
}
for ( xIndex = pE->ixLo; xIndex <= pE->ixHi; xIndex++ ) {
for ( yIndex = pE->iyLo; yIndex <= pE->iyHi; yIndex++ ) {
pNode = nodeArray[ xIndex ][ yIndex ];
if ( pNode != NIL( TWOnode ) ) {
/* Make sure node belongs to this electrode, then
* clear ELCT_ID so that it is not grabbed again.
*/
if (pNode->ELCT_ID == id) {
pNew->pNodes[ nIndex++ ] = pNode;
pNode->ELCT_ID = 0;
}
}
}
}
}
pDevice->pLastContact = pTail;
}