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

📄 meshset.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
  double hStart, hEnd, hMax, hBig;  double ratStart, ratEnd;  int error = OK;  char errBuf[512];/* Initialize list of coordinates. */  *coordList = endCoord = NIL(MESHcoord);  *numCoords = totCoords = 0;/* Check the card list. */  if (error = MESHcheck( dim, cardList )) return( error );/* Print info header. */ #ifdef NOTDEF  fprintf( stdout, " %c.Mesh Card Information\n", toupper(dim) );  fprintf( stdout, "-------------------------\n" );  fprintf( stdout, " %3s %3s %3s %9s %9s %9s %9s %9s %9s\n",      "n.s", "n.m", "n.e", "l.e", "h.s", "h.e", "h.m", "r.s", "r.e" );#endif  for ( card = cardList; card != NIL(MESHcard); card = card->MESHnextCard ) {    cardNum++;    locStart = card->MESHlocStart;    locEnd = card->MESHlocEnd;    if (locEnd == locStart) {		/* This card has no width. *//* First update the node number. */      if (card->MESHnumberGiven) {	if (card->MESHlocationGiven) {	/* Absolute node number given */	  numEnd = card->MESHnumber;	  if (cardNum == 1) numStart = numEnd;	}	else {				/* Number of spaces instead */	  numEnd = numStart + card->MESHnumber;	}      }/* Are node numbers in the wrong order? */      if ( numEnd < numStart ) {	sprintf( errBuf,	    "%c.mesh card %d has out-of-order node numbers ( %d > %d )",	    dim, cardNum, numStart, numEnd );	SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );	error = E_PRIVATE;      }    }    else {				/* This card has some width. *//* First update the node number. */      if (card->MESHnumberGiven) {	/* Uniform mesh */	if (card->MESHlocationGiven) {	/* Absolute node number given */	  numEnd = card->MESHnumber;	  if (cardNum == 1) numStart = numEnd;	  nspStart = numEnd - numStart;	}	else {				/* Number of spaces instead */	  nspStart = card->MESHnumber;	  numEnd = numStart + nspStart;	}	ratStart = 1.0;	ratEnd = 0.0;	nspEnd = 0;	nspMax = 0;        if ( nspStart > 0 ) {	  card->MESHhStart = (locEnd - locStart) / (double)nspStart;	  card->MESHhEnd = 0.0;	}      }      else {				/* Nonuniform mesh */	error = MESHspacing( card, &ratStart, &ratEnd,	    &nspStart, &nspMax, &nspEnd );	if (error) {	  sprintf( errBuf,	      "%c.mesh card %d can't be spaced automatically",	      dim, cardNum );	  SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );	  return( error );	}	else {	  numEnd = numStart + nspStart + nspMax + nspEnd;	}      }/* Are the node numbers properly ordered? */      if ( numEnd <= numStart ) {	sprintf( errBuf,	    "%c.mesh card %d results in out-of-order node numbers ( %d > %d )",	    dim, cardNum, numStart, numEnd );	SPfrontEnd->IFerror( ERR_FATAL, errBuf, NIL(IFuid) );	error = E_PRIVATE;      }      else {/* Create the new MESHcoord's. */        hStart = card->MESHhStart;	hEnd = card->MESHhEnd;	hMax = card->MESHhMax;	hBig = 0.0;/* Generate the first coord in this section */	location = locStart;	error = addCoord( coordList, &endCoord, ++totCoords, location );	if (error) return(error);/* Generate new coords for the starting section. */        nspLeft = nspStart + nspMax + nspEnd;	if ( nspStart != 0 ) {	  hBig = MAX( hBig, hStart*pow( ratStart, (double) (nspStart - 1) ) );	  space = hStart;	  for ( i = 0; (i < nspStart)&&(nspLeft > 1); i++, nspLeft-- ) {	    location += space;	    space *= ratStart;	    error = addCoord( coordList, &endCoord, ++totCoords, location );	    if (error) return(error);	  }	}/* Generate new coords for the maximum section. */	if ( nspMax != 0 ) {	  hBig = MAX( hBig, hMax );	  space = hMax;	  for ( i = 0; (i < nspMax)&&(nspLeft > 1); i++, nspLeft-- ) {	    location += space;	    error = addCoord( coordList, &endCoord, ++totCoords, location );	    if (error) return(error);	  }	}/* Generate new coords for the ending section. */	if ( nspEnd != 0 ) {	  hBig = MAX( hBig, hEnd*pow( ratEnd, (double) (nspEnd - 1) ) );	  space = hEnd * pow( ratEnd, (double) (nspEnd - 1) );	  for ( i = 0; (i < nspEnd)&&(nspLeft > 1); i++, nspLeft-- ) {	    location += space;	    space /= ratEnd;	    error = addCoord( coordList, &endCoord, ++totCoords, location );	    if (error) return(error);	  }	}#ifdef NOTDEF	fprintf( stdout, "             %9.5f\n", locStart );	fprintf( stdout,	    " %3d %3d %3d           %9.5f %9.5f %9.5f %9.5f %9.5f\n",	    nspStart, nspMax, nspEnd,	    hStart, hEnd, hBig, ratStart, ratEnd );#endif      }    }/* Return now if anything has failed. */    if (error) return(error);/* Advance the node number. */    numStart = numEnd;  }/* * If the mesh is not empty, then the loop above has exited before * adding the final coord to the list. So we need to do that now. */  if (*coordList != NIL(MESHcoord)) {    error = addCoord( coordList, &endCoord, ++totCoords, locEnd );    if (error) return(error);#ifdef NOTDEF    fprintf( stdout, "             %9.5f\n", locEnd );#endif  }#ifdef NOTDEF  fprintf( stdout, "\n" );#endif  *numCoords = totCoords;  return(OK);}/* * Name:	MESHspacing * Purpose:	Find ratios, spacings, and node numbers for a mesh span. * Formals:	< I > card: the input card for this span *		< O > rS: ratio found for spacings at start of span *		< O > rE: ratio found for spacings at end of span *		< O > nS: number of start spaces *		< O > nM: number of max spaces *		< O > nE: number of end spaces * Returns:	OK / E_PRIVATE * Users:	MESHsetup * Calls:	oneSideSpacing, twoSideSpacing, maxLimSpacing */static intMESHspacing( card, rS, rE, nS, nM, nE )MESHcard *card;double *rS, *rE;int *nS, *nM, *nE;{  int error = OK;  int hStartGiven = card->MESHhStartGiven;  int hEndGiven = card->MESHhEndGiven;  int hMaxGiven = card->MESHhMaxGiven;  double hS = card->MESHhStart;  double hE = card->MESHhEnd;  double hM = card->MESHhMax;  double rW = card->MESHratio;		/* The ratio wanted */  double width;  width = card->MESHlocEnd - card->MESHlocStart;/* Call subsidiary routine depending on how flags are set. */  if      (!hStartGiven &&  hEndGiven && !hMaxGiven ) {/* End section only */    error = oneSideSpacing( width, hE, rW, rE, nE );    *nM = *nS = 0;    *rS = 0.0;  }  else if ( hStartGiven && !hEndGiven && !hMaxGiven ) {/* Start section only */    error = oneSideSpacing( width, hS, rW, rS, nS );    *nM = *nE = 0;    *rE = 0.0;  }  else if ( hStartGiven &&  hEndGiven && !hMaxGiven ) {/* Both a start and an end section */    error = twoSideSpacing( width, hS, hE, rW, rS, rE, nS, nE );    *nM = 0;  }  else if ( hStartGiven && !hEndGiven &&  hMaxGiven ) {/* Limited size in end section */     error = maxLimSpacing(  width, hS, hM, rW, rS, nS, nM );    *nE = 0;    *rE = 1.0;  }  else if (!hStartGiven &&  hEndGiven &&  hMaxGiven ) {/* Limited size in start section */     error = maxLimSpacing(  width, hE, hM, rW, rE, nE, nM );    *nS = 0;    *rS = 1.0;  }  else if ( hStartGiven &&  hEndGiven &&  hMaxGiven ) {/* Limited size somewhere in the middle */    /* NOT IMPLEMENTED */    /*    error = midLimSpacing(  width, hS, hE, hM, rW, rS, rE, nS, nE, nM );    */    error = E_PRIVATE;  }  else {/* Illegal situations */    error = E_PRIVATE;  }  return( error );}/* * Name:	stepsInSpan * Purpose:	Finds the number of steps needed to go a given distance *		while increasing each step by a given ratio. * Formals:	< I > width: size of total distance *		< I > spacing: size of initial step *		< O > ratio: increase with each step * Returns:	number of steps * Users:	spacing routines * Calls:	log */static doublestepsInSpan( width, spacing, ratio )double width, spacing, ratio;{  double nSpaces;/* Handle ratios near 1.0 specially. */  if ( ABS(ratio - 1.0) < 1.0e-4 ) {    nSpaces = (width/spacing);  }  else {    nSpaces = (log(1.0-width*(1.0-ratio)/spacing)/log(ratio));  }  return(nSpaces);}/* * Name:	oneSideSpacing * Purpose:	Find compatible number of spaces and ratio when the spacing *		is constrained at one end of a span. * Formals:	< I > width: width of the span *		< I > spacing: spacing constraint *		< I > rWanted: ideal ratio of one spacing to the next *		< O > rFound: actual ratio discovered *		< O > nFound: number of spaces found * Returns:	OK / E_PRIVATE * Users:	MESHspacing * Calls:	oneSideRatio, stepsInSpan */static intoneSideSpacing( width, spacing, rWanted, rFound, nFound )double width;double spacing;double rWanted, *rFound;int *nFound;{  int nSpaces;			/* Number of spaces */  double rTemp1, rTemp2;	/* For temporarily calc'ed ratios */  char errBuf[80];/* Make sure we can take at least one step. */  if ( width < spacing ) {    sprintf( errBuf,	"one-sided spacing can't find an acceptable solution\n");    SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) );    *rFound = 0.0;    *nFound = 0;    return(E_PRIVATE);  }  nSpaces = (int)stepsInSpan( width, spacing, rWanted );/* Check to see whether a flat span is acceptable. */  if ( ABS(nSpaces*spacing - width) < 1.0e-3*spacing ) {    *rFound = 1.0;    *nFound = nSpaces;    return( OK );  }  else if ( ABS((nSpaces+1)*spacing - width) < 1.0e-3*spacing ) {    *rFound = 1.0;    *nFound = nSpaces + 1;    return( OK );  }/* Too much error involved in flat span means we have to ramp up. */  rTemp1 = rTemp2 = rWanted;  oneSideRatio( width, spacing, &rTemp1, nSpaces );  oneSideRatio( width, spacing, &rTemp2, nSpaces+1 );  if ( (rTemp1 == 0.0) && (rTemp2 == 0.0) ) {    sprintf( errBuf,	"one-sided spacing can't find an acceptable solution\n");    SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) );    *rFound = 0.0;    *nFound = 0;    return(E_PRIVATE);  }  else if (rTemp1 == 0.0) {    *rFound = rTemp2;    *nFound = nSpaces + 1;  }  else if (rTemp2 == 0.0) {    *rFound = rTemp1;    *nFound = nSpaces;  }  else if (ABS(rWanted-rTemp2) < 4.0*ABS(rWanted-rTemp1)) {    *rFound = rTemp2;    *nFound = nSpaces + 1;  }  else {    *rFound = rTemp1;    *nFound = nSpaces;  }  return(OK);}/* * Name:	oneSideRatio * Purpose:	Compute the unique ratio 'r' which satisfies the following *		constraint:  w = hs*(1-r^ns)/(1-r) * Formals:	< I > w : width of a span *		< I > hs: step at one end of the span *		<I/O> argRatio: ratio found, contains initial guess at entry *		< I > ns: number of spaces to use in the span * Returns:	OK / E_PRIVATE * Users:	oneSideSpacing, maxLimSpacing * Calls:	error-message handler */static intoneSideRatio( w, hs, argRatio, ns )double w;double hs;double *argRatio;int ns;{  double funcLow, funcUpp, func;  double ratLow, ratUpp, ratio = *argRatio;  double dns = (double)ns;  int i;/* Get lower bound on solution. */  ratLow = 0.0;  funcLow = hs - w;  if ((funcLow > 0.0) || ((funcLow < 0.0)&&(ns <= 1))) {    *argRatio = 0.0;    return(E_PRIVATE);  }/* Find upper bound on solution. */  ratUpp = ratio;  do {    ratUpp += 0.2;    funcUpp = hs*geomSum(ratUpp, dns) - w;  } while (funcUpp < 0.0);/* Do bisections to find new ratio. */  for ( i=0; i < RAT_LIM; i++ ) {    ratio = ratLow + 0.5 * (ratUpp - ratLow);    func = hs*geomSum(ratio, dns) - w;    if ((func == 0.0) || (ratUpp - ratLow < RAT_TOL)) break;    funcLow = hs*geomSum(ratLow, dns) - w;    if (funcLow*func > 0.0) {      ratLow = ratio;    }    else {      ratUpp = ratio;    }  }  if (i == RAT_LIM) { /* No solution found */    *argRatio = 0.0;    return(E_PRIVATE);  }  else {    *argRatio = ratio;    return(OK);  }}/* Name:	quadRoots * Purpose:	Find real roots of a quadratic equation if they exist. * Formals:	< I > a, b, c: coefficients in ax^2+bx+c *		< O > rp: the root using the positive sqrt value *		< O > rn: the root using the negative sqrt value * Returns:     TRUE / FALSE * Users:       general * Calls:	sqrt */static intquadRoots( a, b, c, rp, rn )double a, b, c;double *rp, *rn;{  double d;			/* Discriminant */  double f;			/* Root factor */  if (a == 0.0) return(FALSE);  if (b == 0.0) {    d = -c/a;    if (d >= 0.0) {      *rn = - (*rp = sqrt(d));    }    else {      return(FALSE);

⌨️ 快捷键说明

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