⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 meshset.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********Copyright 1991 Regents of the University of California.  All rights reserved.Author:	1991 David A. Gates, U. C. Berkeley CAD Group**********//**********Mesh Setup & Query Routines.**********//* Imports */#include "spice.h"#include <stdio.h>#include <math.h>#include "const.h"#include "util.h"#include "cktdefs.h"#include "nummacs.h"#include "meshdefs.h"#include "meshext.h"#include "gendev.h"#include "sperror.h"#include "suffix.h"/* Local Constants */#define CMP_TOL	1.0e-9		/* Tolerance on (double) comparisons */#define RAT_TOL 1.0e-6		/* Error allowed in ratio calc's */#define RAT_LIM	50		/* Maximum number of ratio iterations */#define UM_TO_CM 1.0e-4		/* Micron to centimeter conversion *//* Forward Declarations */#ifdef __STDC__static int oneSideSpacing( double, double, double,    double *, int * );static int twoSideSpacing( double, double, double, double,    double *, double *, int *, int * );static int maxLimSpacing( double, double, double, double,    double *, int *, int * );static int oneSideRatio( double, double, double *, int );static int twoSideRatio( double, double, double, double *, int, int );#elsestatic int oneSideSpacing();static int twoSideSpacing();static int maxLimSpacing();static int oneSideRatio();static int twoSideRatio();#endif/* END OF HEADER *//* * Name:	MESHmkArray * Purpose:	Turn a coordinate list into a coordinate array. * Formals:	< I > coordList: a sorted list of all the coordinates *		< I > numCoords: the length of the listi, if 0 find it * Returns:	a (double) array of those coordinates, with length in a[0] * Users:	routines used to create the final mesh * Calls:	(none) */double *MESHmkArray( coordList, numCoords )MESHcoord *coordList;int numCoords;{  double *array;  MESHcoord *coord;  if ( numCoords <= 0 ) {    numCoords = 0;    for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) {      numCoords++;    }  }  if ( numCoords != 0 ) {    XALLOC( array, double, 1 + numCoords );    numCoords = 0;    array[ 0 ] = (double) numCoords;    numCoords = 1;    for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) {      array[ numCoords++ ] = coord->location;    }    return array;  }  else {    return NIL(double);  }  /* NOTREACHED */}/* * Name:	MESHiBounds * Purpose:	Find the minimum and maximum indices in a mesh list. * Formals:	< I > coordList: a sorted list of all the coordinates * 		< O > ixMin: the minimum index *		< O > ixMax: the maximum index * Returns:	(none) * Users:	routines wanting to fine the ends of a mesh * Calls:	(none) */voidMESHiBounds( coordList, ixMin, ixMax )MESHcoord *coordList;int *ixMin, *ixMax;{  MESHcoord *last;  if (coordList) {   *ixMin = coordList->number;   for ( last = coordList; last->next != NIL(MESHcoord); last = last->next );   *ixMax = last->number;  }  else {   *ixMin = *ixMax = -1;  }}/* * Name:	MESHlBounds * Purpose:	Find the minimum and maximum locations in a mesh list. * Formals:	< I > coordList: a sorted list of all the coordinates * 		< O > lcMin: the minimum location *		< O > lcMax: the maximum location * Returns:	(none) * Users:	routines wanting to find the ends of a mesh * Calls:	(none) */voidMESHlBounds( coordList, lcMin, lcMax )MESHcoord *coordList;double *lcMin, *lcMax;{  MESHcoord *last;  if (coordList) {   *lcMin = coordList->location;   for ( last = coordList; last->next != NIL(MESHcoord); last = last->next );   *lcMax = last->location;  }  else {   *lcMin = *lcMax = 0.0;  }}/* * Name:	MESHlocate * Purpose:	Finds the index of the MESHcoord nearest to a location. * Formals:	< I > coordList: a sorted list of all available coordinates *		< I > location: the location to find * Returns:	index / -1 (list empty) * Users:	routines that convert distances to indices * Calls:	(none) */intMESHlocate( coordList, location )MESHcoord *coordList;double location;{  MESHcoord *coord, *prevCoord = NIL(MESHcoord);  int index;/* Find the coordinates which flank the location. */  for ( coord = coordList; coord != NIL(MESHcoord); coord = coord->next ) {    if ( coord->location > location ) break;    prevCoord = coord;  }/* Get the index. */  if (prevCoord && coord) {    if ( location <= (prevCoord->location + coord->location) / 2.0 ) {      index = prevCoord->number;    }    else {      index = coord->number;    }  }  else if ( coord ) {    index = coord->number;  }  else if ( prevCoord ) {    index = prevCoord->number;  }  else {    index = -1;  }  return( index );}/* * Name:	MESHcheck * Purpose:	Checks a list of mesh cards for input errors. * Formals:	<I/O> cardList: pointer to head of linked list of MESHcard's *		< I > dim: 'x', 'y' or 'z' dimension * Returns:     OK / E_PRIVATE * Users:	setup routines * Calls:	error-message handler */intMESHcheck( dim, cardList )char dim;MESHcard *cardList;{  register MESHcard *card;  int cardNum = 0;  double locStart = 0.0, locEnd;  double ratio;  int error = OK;  char errBuf[512];  if ( cardList == NIL(MESHcard) ) {    sprintf( errBuf,	"%c.mesh card list is empty",	dim );    SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );    locEnd = locStart;    return( E_PRIVATE );  }  for ( card = cardList; card != NIL(MESHcard); card = card->MESHnextCard ) {    cardNum++;/* Am I trying to find number of nodes directly & indirectly? */    if (card->MESHnumberGiven && card->MESHratioGiven) {      sprintf( errBuf,	  "%c.mesh card %d uses both number and ratio - number ignored",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) );      card->MESHnumberGiven = FALSE;    }/* Will I be able to locate endpoints? */    if (!card->MESHlocationGiven && !card->MESHwidthGiven) {      sprintf( errBuf,	  "%c.mesh card %d has no distances",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );      locEnd = locStart;      error = E_PRIVATE;    }    else if (card->MESHlocationGiven && card->MESHwidthGiven) {      sprintf( errBuf,	  "%c.mesh card %d uses both location and width - location ignored",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) );      card->MESHlocationGiven = FALSE;      locEnd = locStart + card->MESHwidth;    }    else if (card->MESHlocationGiven) {      locEnd = card->MESHlocation;      if (cardNum == 1) locStart = locEnd;    }    else {      locEnd = locStart + card->MESHwidth;    }/* Are the endpoints in the wrong order? */    if ( locEnd - locStart < - CMP_TOL ) {      sprintf( errBuf,	  "%c.mesh card %d uses negative width",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );      error = E_PRIVATE;    }/* Are the endpoints too close together? */    else if ( (locEnd - locStart <= CMP_TOL) ) {      if ( !(cardNum == 1 && locStart == locEnd) ) {	sprintf( errBuf,	    "%c.mesh card %d has negligible width - ignored",	    dim, cardNum );	SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) );	locStart = locEnd;      }    }/* Is the ratio out of the acceptable range? */    if (card->MESHratioGiven) {      ratio = card->MESHratio;    }    else {      ratio = 1.0;    }    if ((ratio < 1.0) || (ratio > 10.0)) {      sprintf( errBuf,	  "%c.mesh card %d has ratio out of range - reset to 1.0",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_INFO, errBuf, NIL(IFuid) );      ratio = 1.0;    }/* Check sizes of h.start, h.end and h.max. */    if ((card->MESHhStartGiven && (card->MESHhStart <= 0.0)) ||	(card->MESHhEndGiven && (card->MESHhEnd <= 0.0)) ||	(card->MESHhMaxGiven && (card->MESHhMax <= 0.0))) {      sprintf( errBuf,	  "%c.mesh card %d wants to use a non-positive spacing",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );      error = E_PRIVATE;    }/* Is the max spacing being used improperly? */    if (card->MESHhMaxGiven && (	( card->MESHhStartGiven &&  card->MESHhEndGiven) ||	(!card->MESHhStartGiven && !card->MESHhEndGiven))) {      sprintf( errBuf,	  "%c.mesh card %d needs to use one of h.start or h.end with h.max",	  dim, cardNum );      SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );      error = E_PRIVATE;    }    else if (card->MESHhMaxGiven && card->MESHhStartGiven) {      if (card->MESHhStart > card->MESHhMax) {	sprintf( errBuf,	    "%c.mesh card %d wants h.start > h.max",	    dim, cardNum );	SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );	error = E_PRIVATE;      }      else {	card->MESHhEnd = card->MESHhMax;      }    }    else if (card->MESHhMaxGiven && card->MESHhEndGiven) {      if (card->MESHhEnd > card->MESHhMax) {	sprintf( errBuf,	    "%c.mesh card %d wants h.end > h.max",	    dim, cardNum );	SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );	error = E_PRIVATE;      }      else {	card->MESHhStart = card->MESHhMax;      }    }/* Return now if anything has failed. */    if (error) return(error);/* Note: at this point we still aren't sure whether node numbers are OK. *//* Fill-in newly computed information. */    card->MESHlocStart = locStart;    card->MESHlocEnd = locEnd;    card->MESHratio = ratio;/* Advance current location. */    locStart = locEnd;  }  return(OK);}/* * Name:	geomSum * Purpose:	Computes the sum of n terms of a geometric series. * Formals:	< I > r: ratio of one term to the next *		< I > n: number of terms to sum * Returns:	sum / 0.0 * Users:	spacing routines * Calls:	pow */static doublegeomSum( r, n )double r;double n;{  double sum;  if ((r < 0.0) || (n <= 0.0)) {    sum = 0.0;  }  else if (r == 0.0) {    sum = 1.0;  }  else {    if (ABS(r - 1.0) < 1.0e-4) {      sum = n * (1.0 + (n - 1.0)*(r - 1.0)/2.0);    }    else {      sum = (1.0 - pow(r,n))/(1.0 - r);    }  }  return( sum );}/* * Name:	addCoord * Purpose:	add a new coordinate to the tail of a linked list * Formals:	<I/O> head: head of linked list *		<I/O> tail: tail of linked list *		< I > number: node number of coordinate *		< I > location: location of coordinate * Returns:	OK / E_NOMEM * Users:	MESHsetup * Calls:	memory allocator */static intaddCoord( head, tail, number, location )MESHcoord **head, **tail;int number;double location;{  MESHcoord *newCoord;  if (*head == NIL(MESHcoord)) {    RALLOC( *tail, MESHcoord, 1 );    newCoord = *head = *tail;  }  else {    RALLOC( (*tail)->next, MESHcoord, 1 );    newCoord = *tail = (*tail)->next;  }  newCoord->next = NIL(MESHcoord);  newCoord->number = number;  newCoord->location = location * UM_TO_CM;  return(OK);}/* * Name:	MESHsetup * Purpose:	Converts a list of input MESHcard's to a list of MESHcoord's. *		Expansion is performed so that node numbers in the final list *		increase by one from coordinate to coordinate.  The list *		will grow until the input ends or a bad card is found. * Formals:	< I > dim: 'x', 'y', or 'z' dimension *		<I/O> cardList: the list of input cards *		< O > coordList: the final list of coordinates *		< O > numCoords: the number of coords in coordList * Returns:	OK / E_PRIVATE * Users:	numerical device setup routines * Calls:	MESHcheck, MESHspacing, error-message handler */intMESHsetup( dim, cardList, coordList, numCoords )char dim;MESHcard *cardList;MESHcoord **coordList;int *numCoords;{  register MESHcard *card;  MESHcoord *endCoord;  int cardNum = 0;  int i, totCoords, numStart=1, numEnd, nspStart, nspEnd, nspMax, nspLeft;  double locStart, locEnd, location, space;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -