コード例 #1
0
ファイル: domnset.c プロジェクト: a-mehrabian/spice-buffer
/*
 * Name:	DOMNsetup
 * Purpose:	convert a list of DOMNcard's to DOMNdomain's
 * Formals:	cardList: list of cards to setup
 *		domainList: returns the list of DOMNdomain's
 *		xMeshList: list of coordinates in the x mesh
 *		yMeshList: list of coordinates in the y mesh
 * Returns:	OK/E_PRIVATE
 * Users:	 numerical devices
 * Calls:	DOMNcheck
 */
int
DOMNsetup(DOMNcard *cardList, DOMNdomain **domainList, MESHcoord *xMeshList, 
          MESHcoord *yMeshList, MaterialInfo *materialList)
{
  DOMNcard *card;
  DOMNdomain *newDomain = NULL;
  int ixMin, ixMax, iyMin, iyMax;
  int cardNum = 0;
  int error;
  char ebuf[512];		/* error message buffer */

/* Initialize list of domains */
  *domainList = NULL;

/* Check the card list */
  if ((error = DOMNcheck( cardList, materialList )) != 0) return( error );

/* Find the limits on the indices */
  MESHiBounds( xMeshList, &ixMin, &ixMax );
  MESHiBounds( yMeshList, &iyMin, &iyMax );

  error = OK;
  for ( card = cardList; card != NULL; card = card->DOMNnextCard ) {
    cardNum++;

    if (*domainList == NULL) {
      RALLOC( newDomain, DOMNdomain, 1 );
      *domainList = newDomain;
    } else {
      RALLOC( newDomain->next, DOMNdomain, 1 );
      newDomain = newDomain->next;
    }

    newDomain->id = card->DOMNnumber;
    newDomain->material = card->DOMNmaterial;
    newDomain->next = NULL;

    if (card->DOMNixLowGiven) {
      newDomain->ixLo = MAX(card->DOMNixLow, ixMin);
    }
    else if (card->DOMNxLowGiven) {
      newDomain->ixLo = MESHlocate( xMeshList, card->DOMNxLow );
    }
    else {
      newDomain->ixLo = ixMin;
    }
    if (card->DOMNixHighGiven) {
      newDomain->ixHi = MIN(card->DOMNixHigh, ixMax);
    }
    else if (card->DOMNxHighGiven) {
      newDomain->ixHi = MESHlocate( xMeshList, card->DOMNxHigh );
    }
    else {
      newDomain->ixHi = ixMax;
    }
    if (newDomain->ixLo > newDomain->ixHi) {
      sprintf( ebuf,
	  "domain card %d has low x index (%d) > high x index (%d)",
	  cardNum, newDomain->ixLo, newDomain->ixHi );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NULL );
      error = E_PRIVATE;
    }
    if (card->DOMNiyLowGiven) {
      newDomain->iyLo = MAX(card->DOMNiyLow, iyMin);
    }
    else if (card->DOMNyLowGiven) {
      newDomain->iyLo = MESHlocate( yMeshList, card->DOMNyLow );
    }
    else {
      newDomain->iyLo = iyMin;
    }
    if (card->DOMNiyHighGiven) {
      newDomain->iyHi = MIN(card->DOMNiyHigh, iyMax);
    }
    else if (card->DOMNyHighGiven) {
      newDomain->iyHi = MESHlocate( yMeshList, card->DOMNyHigh );
    }
    else {
      newDomain->iyHi = iyMax;
    }
    if (newDomain->iyLo > newDomain->iyHi) {
      sprintf( ebuf,
	  "domain card %d has low y index (%d) > high y index (%d)",
	  cardNum, newDomain->iyLo, newDomain->iyHi );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NULL );
      error = E_PRIVATE;
    }
  }
  return( error );
}
コード例 #2
0
/*
 * Name:	BDRYsetup
 * Purpose:	Checks BDRY cards and then sets the indices
 * Formals:	cardList: list of cards to setup, returns with indices set
 *		xMeshList: list of coordinates in the x mesh
 *		yMeshList: list of coordinates in the y mesh
 * Returns:	OK/E_PRIVATE
 * Users:	 numerical devices
 * Calls:	BDRYcheck
 */
int
BDRYsetup(BDRYcard *cardList, MESHcoord *xMeshList, MESHcoord *yMeshList,DOMNdomain *domnList)
{
  BDRYcard *card;
  int ixMin, ixMax, iyMin, iyMax;
  int cardNum = 0;
  int error;
  char ebuf[512];		/* error message buffer */

/* Check the card list */
  if ((error = BDRYcheck( cardList, domnList ))) return( error );

/* Find the limits on the indices */
  MESHiBounds( xMeshList, &ixMin, &ixMax );
  MESHiBounds( yMeshList, &iyMin, &iyMax );

  error = OK;
  for ( card = cardList; card != NIL(BDRYcard); card = card->BDRYnextCard ) {
    cardNum++;

    if (card->BDRYixLowGiven) {
      card->BDRYixLow = MAX(card->BDRYixLow, ixMin);
    }
    else if (card->BDRYxLowGiven) {
      card->BDRYixLow = MESHlocate( xMeshList, card->BDRYxLow );
    }
    else {
      card->BDRYixLow = ixMin;
    }
    if (card->BDRYixHighGiven) {
      card->BDRYixHigh = MIN(card->BDRYixHigh, ixMax);
    }
    else if (card->BDRYxHighGiven) {
      card->BDRYixHigh = MESHlocate( xMeshList, card->BDRYxHigh );
    }
    else {
      card->BDRYixHigh = ixMax;
    }
    if (card->BDRYixLow > card->BDRYixHigh) {
      sprintf( ebuf,
	  "boundary card %d has low x index (%d) > high x index (%d)",
	  cardNum, card->BDRYixHigh, card->BDRYixLow );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );
      error = E_PRIVATE;
    }
    if (card->BDRYiyLowGiven) {
      card->BDRYiyLow = MAX(card->BDRYiyLow, iyMin);
    }
    else if (card->BDRYyLowGiven) {
      card->BDRYiyLow = MESHlocate( yMeshList, card->BDRYyLow );
    }
    else {
      card->BDRYiyLow = iyMin;
    }
    if (card->BDRYiyHighGiven) {
      card->BDRYiyHigh = MIN(card->BDRYiyHigh, iyMax);
    }
    else if (card->BDRYyHighGiven) {
      card->BDRYiyHigh = MESHlocate( yMeshList, card->BDRYyHigh );
    }
    else {
      card->BDRYiyHigh = iyMax;
    }
    if (card->BDRYiyLow > card->BDRYiyHigh) {
      sprintf( ebuf,
	  "boundary card %d has low y index (%d) > high y index (%d)",
	  cardNum, card->BDRYiyHigh, card->BDRYiyLow );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NIL(IFuid) );
      error = E_PRIVATE;
    }
  }
  return( error );
}
コード例 #3
0
ファイル: elctset.c プロジェクト: a-mehrabian/spice-buffer
/*
 * Name:	ELCTsetup
 * Purpose:	convert a list of ELCTcard's to ELCTelectrode's
 * Formals:	cardList: list of cards to setup
 *		electrodeList: returns the list of ELCTelectrode's
 *		xMeshList: list of coordinates in the x mesh
 *		yMeshList: list of coordinates in the y mesh
 * Returns:	OK/E_PRIVATE
 * Users:	 numerical devices
 * Calls:	ELCTcheck
 */
int
ELCTsetup(ELCTcard *cardList, ELCTelectrode **electrodeList, 
          MESHcoord *xMeshList, MESHcoord *yMeshList)
{
  ELCTcard *card;
  ELCTelectrode *newElectrode = NULL;
  int ixMin, ixMax, iyMin, iyMax;
  int cardNum = 0;
  int error;
  char ebuf[512];		/* error message buffer */

/* Initialize list of electrodes */
  *electrodeList = NULL;

/* Check the card list */
  if ((error = ELCTcheck( cardList )) != 0) return( error );

/* Find the limits on the indices */
  MESHiBounds( xMeshList, &ixMin, &ixMax );
  MESHiBounds( yMeshList, &iyMin, &iyMax );

  error = OK;
  for ( card = cardList; card != NULL; card = card->ELCTnextCard ) {
    cardNum++;

    if (*electrodeList == NULL) {
      RALLOC( newElectrode, ELCTelectrode, 1 );
      *electrodeList = newElectrode;
    } else {
      RALLOC( newElectrode->next, ELCTelectrode, 1 );
      newElectrode = newElectrode->next;
    }
    newElectrode->next = NULL;
    newElectrode->id = card->ELCTnumber;
    newElectrode->workf = 4.10 /* electron volts */;

    if (card->ELCTixLowGiven) {
      newElectrode->ixLo = MAX(card->ELCTixLow, ixMin);
    }
    else if (card->ELCTxLowGiven) {
      newElectrode->ixLo = MESHlocate( xMeshList, card->ELCTxLow );
    }
    else {
      newElectrode->ixLo = ixMin;
    }
    if (card->ELCTixHighGiven) {
      newElectrode->ixHi = MIN(card->ELCTixHigh, ixMax);
    }
    else if (card->ELCTxHighGiven) {
      newElectrode->ixHi = MESHlocate( xMeshList, card->ELCTxHigh );
    }
    else {
      newElectrode->ixHi = ixMax;
    }
    if (newElectrode->ixLo > newElectrode->ixHi) {
      sprintf( ebuf,
	  "electrode card %d has low x index (%d) > high x index (%d)",
	  cardNum, newElectrode->ixLo, newElectrode->ixHi );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NULL );
      error = E_PRIVATE;
    }
    if (card->ELCTiyLowGiven) {
      newElectrode->iyLo = MAX(card->ELCTiyLow, iyMin);
    }
    else if (card->ELCTyLowGiven) {
      newElectrode->iyLo = MESHlocate( yMeshList, card->ELCTyLow );
    }
    else {
      newElectrode->iyLo = iyMin;
    }
    if (card->ELCTiyHighGiven) {
      newElectrode->iyHi = MIN(card->ELCTiyHigh, iyMax);
    }
    else if (card->ELCTyHighGiven) {
      newElectrode->iyHi = MESHlocate( yMeshList, card->ELCTyHigh );
    }
    else {
      newElectrode->iyHi = iyMax;
    }
    if (newElectrode->iyLo > newElectrode->iyHi) {
      sprintf( ebuf,
	  "electrode card %d has low y index (%d) > high y index (%d)",
	  cardNum, newElectrode->iyLo, newElectrode->iyHi );
      SPfrontEnd->IFerror( ERR_WARNING, ebuf, NULL );
      error = E_PRIVATE;
    }
  }
  return( error );
}
コード例 #4
0
int 
NBJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
/*
 * load the diode structure with those pointers needed later for fast matrix
 * loading
 */
{
  register NBJTmodel *model = (NBJTmodel *) inModel;
  register NBJTinstance *inst;
  METHcard *methods;
  MODLcard *models;
  OPTNcard *options;
  OUTPcard *outputs;
  int error;
  int xMeshSize;
  ONEdevice *pDevice;
  ONEcoord *xCoordList = NULL;
  ONEdomain *domainList = NULL;
  DOPprofile *profileList = NULL;
  DOPtable *dopTableList = NULL;
  ONEmaterial *pM, *pMaterial = NULL, *materialList = NULL;
  double startTime;


  /* loop through all the diode models */
  for (; model != NULL; model = model->NBJTnextModel) {
    if (!model->NBJTpInfo) {
      TSCALLOC(model->NBJTpInfo, 1, ONEtranInfo);
    }
    methods = model->NBJTmethods;
    if (!methods) {
      TSCALLOC(methods, 1, METHcard);
      model->NBJTmethods = methods;
    }
    models = model->NBJTmodels;
    if (!models) {
      TSCALLOC(models, 1, MODLcard);
      model->NBJTmodels = models;
    }
    options = model->NBJToptions;
    if (!options) {
      TSCALLOC(options, 1, OPTNcard);
      model->NBJToptions = options;
    }
    outputs = model->NBJToutputs;
    if (!outputs) {
      TSCALLOC(outputs, 1, OUTPcard);
      model->NBJToutputs = outputs;
    }
    if (!methods->METHvoltPredGiven) {
      methods->METHvoltPred = FALSE;
    }
    if (!methods->METHmobDerivGiven) {
      methods->METHmobDeriv = TRUE;
    }
    if (!methods->METHoneCarrierGiven) {
      methods->METHoneCarrier = FALSE;
    }
    if (!methods->METHacAnalysisMethodGiven) {
      methods->METHacAnalysisMethod = SOR;
    }
    if (!methods->METHdabstolGiven) {
      methods->METHdabstol = DABSTOL1D;
    }
    if (!methods->METHdreltolGiven) {
      methods->METHdreltol = ckt->CKTreltol;
    }
    if (!methods->METHitLimGiven) {
      methods->METHitLim = 20;
    }
    if (!methods->METHomegaGiven || methods->METHomega <= 0.0) {
      methods->METHomega = 2.0 * M_PI /* radians/sec */ ;
    }
    if (!options->OPTNdefaGiven || options->OPTNdefa <= 0.0) {
      options->OPTNdefa = 1.0e4 /* cm^2 */ ;
    }
    if (!options->OPTNbaseLengthGiven) {
      options->OPTNbaseLength = 0.0;
    }
    if (!options->OPTNbaseAreaGiven) {
      options->OPTNbaseArea = 1.0;
    }
    if (!options->OPTNdeviceTypeGiven) {
      options->OPTNdeviceType = OPTN_BIPOLAR;
    }
    if (!options->OPTNicFileGiven) {
      options->OPTNicFile = NULL;
      options->OPTNunique = FALSE;		/* Can't form a unique name. */
    }
    if (!options->OPTNuniqueGiven) {
      options->OPTNunique = FALSE;
    }

    /* Set up the rest of the card lists */
    if ((error = MODLsetup(model->NBJTmodels)) != 0)
      return (error);
    BandGapNarrowing = models->MODLbandGapNarrowing;
    ConcDepLifetime = models->MODLconcDepLifetime;
    TempDepMobility = models->MODLtempDepMobility;
    ConcDepMobility = models->MODLconcDepMobility;

    if ((error = OUTPsetup(model->NBJToutputs)) != 0)
      return (error);
    if ((error = MATLsetup(model->NBJTmaterials, &materialList)) != 0)
      return (error);
    if ((error = MOBsetup(model->NBJTmobility, materialList)) != 0)
      return (error);
    if ((error = MESHsetup('x', model->NBJTxMeshes, &xCoordList, &xMeshSize)) != 0)
      return (error);
    if ((error = DOMNsetup(model->NBJTdomains, &domainList,
	    xCoordList, NULL, materialList)) != 0)
      return (error);
    if ((error = BDRYsetup(model->NBJTboundaries,
	    xCoordList, NULL, domainList)) != 0)
      return (error);
    if ((error = CONTsetup(model->NBJTcontacts, NULL)) != 0)
      return (error);
    if ((error = DOPsetup(model->NBJTdopings, &profileList,
	    &dopTableList, xCoordList, NULL)) != 0)
      return (error);
    model->NBJTmatlInfo = materialList;
    model->NBJTprofiles = profileList;
    model->NBJTdopTables = dopTableList;

    /* loop through all the instances of the model */
    for (inst = model->NBJTinstances; inst != NULL;
	inst = inst->NBJTnextInstance) {

      startTime = SPfrontEnd->IFseconds();

      if (!inst->NBJTprintGiven) {
	inst->NBJTprint = 0;
      } else if (inst->NBJTprint <= 0) {
	inst->NBJTprint = 1;
      }
      if (!inst->NBJTicFileGiven) {
	if (options->OPTNunique) {
	  inst->NBJTicFile = tprintf("%s.%s", options->OPTNicFile, inst->NBJTname);
	} else if (options->OPTNicFile != NULL) {
	  inst->NBJTicFile = tprintf("%s", options->OPTNicFile);
	} else {
	  inst->NBJTicFile = NULL;
	}
      }
      inst->NBJTstate = *states;
      *states += NBJTnumStates;

      if (!inst->NBJTpDevice) {
	/* Assign the mesh info to each instance. */
	TSCALLOC(pDevice, 1, ONEdevice);
	TSCALLOC(pDevice->pStats, 1, ONEstats);
	pDevice->name = inst->NBJTname;
	pDevice->solverType = SLV_NONE;
	pDevice->numNodes = xMeshSize;
	pDevice->abstol = methods->METHdabstol;
	pDevice->reltol = methods->METHdreltol;
	pDevice->rhsImag = NULL;
	TSCALLOC(pDevice->elemArray, pDevice->numNodes, ONEelem *);

	/* Create a copy of material data that can change with temperature. */
	pDevice->pMaterials = NULL;
	for (pM = materialList; pM != NULL; pM = pM->next) {
	  if (pDevice->pMaterials == NULL) {
	    TSCALLOC(pMaterial, 1, ONEmaterial);
	    pDevice->pMaterials = pMaterial;
	  } else {
	    TSCALLOC(pMaterial->next, 1, ONEmaterial);
	    pMaterial = pMaterial->next;
	  }
	  /* Copy everything, then fix the incorrect pointer. */
	  memcpy(pMaterial, pM, sizeof(ONEmaterial));
	  pMaterial->next = NULL;
	}

	/* generate the mesh structure for the device */
	ONEbuildMesh(pDevice, xCoordList, domainList, pDevice->pMaterials);

	if (options->OPTNbaseDepthGiven) {
	  /* The base contact depth has been specified in the input. */
	  pDevice->baseIndex = MESHlocate(xCoordList, options->OPTNbaseDepth);
	} else {
	  pDevice->baseIndex = -1;	/* Invalid index acts as a flag */
	}
	/* store the device info in the instance */
	inst->NBJTpDevice = pDevice;
      }
      /* Now update the state pointers. */
      ONEgetStatePointers(inst->NBJTpDevice, states);

      /* Wipe out statistics from previous runs (if any). */
      memset(inst->NBJTpDevice->pStats, 0, sizeof(ONEstats));

      inst->NBJTpDevice->pStats->totalTime[STAT_SETUP] +=
	  SPfrontEnd->IFseconds() - startTime;

      /* macro to make elements with built in test for out of memory */
#define TSTALLOC(ptr,first,second) \
do { if ((inst->ptr = SMPmakeElt(matrix, inst->first, inst->second)) == NULL){\
  return(E_NOMEM);\
} } while(0)

      TSTALLOC(NBJTcolColPtr, NBJTcolNode, NBJTcolNode);
      TSTALLOC(NBJTbaseBasePtr, NBJTbaseNode, NBJTbaseNode);
      TSTALLOC(NBJTemitEmitPtr, NBJTemitNode, NBJTemitNode);
      TSTALLOC(NBJTcolBasePtr, NBJTcolNode, NBJTbaseNode);
      TSTALLOC(NBJTcolEmitPtr, NBJTcolNode, NBJTemitNode);
      TSTALLOC(NBJTbaseColPtr, NBJTbaseNode, NBJTcolNode);
      TSTALLOC(NBJTbaseEmitPtr, NBJTbaseNode, NBJTemitNode);
      TSTALLOC(NBJTemitColPtr, NBJTemitNode, NBJTcolNode);
      TSTALLOC(NBJTemitBasePtr, NBJTemitNode, NBJTbaseNode);
    }
    /* Clean up lists */
    killCoordInfo(xCoordList);
    killDomainInfo(domainList);
  }