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

📄 meshset.c

📁 spice中支持多层次元件模型仿真的可单独运行的插件源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    }  }  else {    d = 1.0 - 4*a*c/(b*b);    if (d >= 0.0) {      f = (1.0 + sqrt(d))/2.0;      *rp = - (b*f)/a;      *rn = - c/(b*f);    }    else {      return(FALSE);    }  }  return(TRUE);}/* * Name:	twoSideSpacing * Purpose:	Find a compatible set of ratios and node numbers when the *		spacing is constrained at both ends of a span. * Formals:	< I > width: size the span *		< I > hStart: spacing at start of span *		< I > hEnd: spacing at end of span *		< I > rWanted: desired ratio of spacings *		< O > rSfound: ratio found for start of span *		< O > rEfound: ratio found for end of span *		< O > nSfound: number of start spaces *		< O > nEfound: number of end spaces * Returns:	OK / E_PRIVATE * Users:	MESHspacing * Calls:	twoSideRatio, error-message handler */static inttwoSideSpacing( width, hStart, hEnd, rWanted, rSfound, rEfound,		nSfound, nEfound )double width;double hStart, hEnd;double rWanted, *rSfound, *rEfound;int *nSfound, *nEfound;{  int nSpaceS;			/* Number of spaces at the start */  int nSpaceE;			/* Number of spaces at the end */  int nSpaceT;			/* Number of spaces total */  double dSpaceS;		/* Exact value of nSpaceS */  double dSpaceE;		/* Exact value of nSpaceE */  double dSpaceT;		/* Exact value of nSpaceT */  double dDiff;			/* Difference between dSpaceS & dSpaceE */  double remaining;		/* Length of span between hs and he */  double rTempS, rTempE;	/* For temporarily calc'ed ratios */  double hsLast, heLast;	/* Used to ensure ratio is valid */  double rConnect, rMin, rMax;  /* " */  double hMax, hMin;		/* Max and min between hStart and hEnd */  double tmp;  int i,j;			/* Indices for searching for best ratio */  int solnFound;		/* For partial search termination */  int solnError;		/* For partial search termination */  int nSaveS = 0;		/* Saves best solution so far */  int nSaveE = 0;		/* " */  double rSaveS = 0.0;		/* " */  double rSaveE = 0.0;		/* " */  char errBuf[80];/* * It's an error if there isn't enough width to fit in both spaces. */  remaining = width - (hStart + hEnd);  if (remaining < 0.0) {    sprintf( errBuf,	"two-sided spacing can't find an acceptable solution\n");    SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) );    *rSfound = *rEfound = 0.0;    *nSfound = *nEfound = 0;    return(E_PRIVATE);  }/* Adjust ratio wanted to acceptable limits, and find number of extra spaces * needed to bring the smaller ratio up to the size of the bigger one. */  hMax = MAX( hStart, hEnd );  hMin = MIN( hStart, hEnd );  if ( hMax == hMin ) {    dDiff = 0.0;  }  else {/* Does a solution exist if we allow the number of spaces to take on  * a non-integral value? * If not, then adjust the ratio to lie within acceptable bounds. * Since the choice of whether or not to require a peak in the plot * of "spacing vs number" is arbitrary, both cases are checked, and * the one that gives the closest answer to the original ratio * is chosen.  The function quadRoots is used to find limits for the * ratio in the peaked case.  The unpeaked case can find a lower * bound more easily. */    if (quadRoots( hMax, hMax - width, remaining, &rTempS, &rTempE )) {      rWanted = MIN(rWanted, rTempS);      rTempS = 1.0 + (hMax - hMin)/(width - hMax);      rWanted = MAX(rWanted, rTempS);      if ((rWanted != rTempS) && (rTempE > rWanted)) {	if (ABS(rWanted - rTempE) < 4.0*ABS(rWanted - rTempS)) {	  rWanted = rTempE;	}	else {	  rWanted = rTempS;	}      }    }    else { /* Complex roots */      rTempS = 1.0 + (hMax - hMin)/(width - hMax);      rWanted = MAX(rWanted, rTempS);    }    dDiff = log(hMax/hMin)/log(rWanted);    dDiff *= ( hStart < hEnd ) ? -1.0 : 1.0;  }/* Find the number of spaces at the start and at the end. *//* Handle ratio near 1.0 carefully. */  if ( ABS(rWanted - 1.0) < 1.0e-4 ) {    dSpaceS = (width - dDiff*hEnd)/(hStart+hEnd);  }  else {    tmp = (hStart+hEnd-width+width*rWanted)/      (hStart+hEnd*pow(rWanted,dDiff));    dSpaceS = log(tmp)/log(rWanted);  }  dSpaceE = dSpaceS + dDiff;  dSpaceT = dSpaceS + dSpaceE;/* Search until an acceptable solution is found.  Some * cases may be repeated, but no harm is done. */  for (i = 0; i <= 1; i++) {    nSpaceT = (int)dSpaceT + i;/* Guess a starting point which is guaranteed to have a solution. */    nSpaceS = MIN( nSpaceT - 1, MAX( 4, (int) dSpaceS) );    nSpaceE = nSpaceT - nSpaceS;    solnFound = solnError = FALSE;    while ( !solnFound ) { /* Take care of special cases first. */      if ((nSpaceE <= 0) || (nSpaceS <= 0)) {	solnError = TRUE;      }      else if (nSpaceT == 2) { 	/* Check for exact fit */	if (ABS(remaining) < 1.0e-3*hMax ) {	  rTempS = hEnd / hStart;	  rTempE = 1.0 / rTempS;	  nSpaceS = nSpaceE = 1;	}	else {	  solnError = TRUE;	}      }      else if (nSpaceT == 3) { 	/* Trivial to solve */	if (remaining > 0.0) {	  rTempS = remaining / hStart;	  rTempE = remaining / hEnd;	  nSpaceS = 2;		/* Always put middle space at start */	  nSpaceE = 1;	}	else {	  solnError = TRUE;	}      }      else { /* Finally, the general case */	if (remaining > 0.0) {	  rTempS = rWanted;	  twoSideRatio( width, hStart, hEnd, &rTempS, nSpaceS, nSpaceE );	  rTempE = rTempS;	}	else {	  solnError = TRUE;	}      }      if ( solnError )	break;		/* while loop *//* Check whether the ratio discovered is good or not. */      hsLast = hStart*pow(rTempS, (double)nSpaceS-1.0);      heLast = hEnd*pow(rTempE, (double)nSpaceE-1.0);      rConnect = heLast/hsLast;      if ( rConnect < 1.0/rTempE - RAT_TOL ) {	nSpaceS--;	nSpaceE++;      }      else if ( rConnect > rTempS + RAT_TOL ) {	nSpaceS++;	nSpaceE--;      }      else {	solnFound = TRUE;/* Save if this solution is better than the previous one. */	if (ABS(rWanted - rTempS) <= ABS(rWanted - rSaveS)) {	  rSaveS = rTempS;	  rSaveE = rTempE;	  nSaveS = nSpaceS;	  nSaveE = nSpaceE;	}      }    }  }/* Prepare return values. */  if (rSaveS == 0.0) {    sprintf( errBuf,	"two-sided spacing can't find an acceptable solution\n");    SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) );    *rSfound = *rEfound = 0.0;    *nSfound = *nEfound = 0;    return(E_PRIVATE);  }  else {    *rSfound = rSaveS;    *rEfound = rSaveE;    *nSfound = nSaveS;    *nEfound = nSaveE;    return(OK);  }}/* * Name:	twoSideRatio * Purpose:	Finds the unique ratio 'r' which satisfies the *		constraint: *			w = hs*(1-r^ns)/(1-r) + he*(1-r^ne)/(1-r) * Formals:	< I > w:  size of a span *		< I > hs: spacing at start of span *		< I > he: spacing at end of span *		<I/O> argRatio: returns r, contains initial guess for r *		< I > ns: number of steps to take at start *		< I > ne: number of steps to take at end * Returns:	OK / E_PRIVATE * Users:	twoSideSpacing * Calls:	error-message handler */static inttwoSideRatio( w, hs, he, argRatio, ns, ne )double w;double hs, he;double *argRatio;int ns, ne;{  double funcLow, funcUpp, func;  double ratLow, ratUpp, ratio = *argRatio;  double dns = (double)ns;  double dne = (double)ne;  int i;/* Get lower bound on solution. */  ratLow = 0.0;  funcLow = hs + he - w;  if ((funcLow > 0.0) || ((funcLow < 0.0) && (MAX(ns,ne) <= 1))) {    *argRatio = 0.0;    return(E_PRIVATE);  }/* Find upper bound on solution. */  ratUpp = ratio;  do {    ratUpp += 0.2;    funcUpp = hs*geomSum(ratUpp, dns) + he*geomSum(ratUpp, dne) - 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) + he*geomSum(ratio, dne) - w;    if ((func == 0.0) || (ratUpp - ratLow < RAT_TOL)) break;    funcLow = hs*geomSum(ratLow, dns) + he*geomSum(ratLow, dne) - 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:	maxLimSpacing * Purpose:	Find compatible number of spaces and ratio when the spacing *		is constrained at start of a span, and has to be smaller *		than a user-specified maximum at the end. * Formals:	< I > width: width of the span *		< I > hStart: spacing constraint at one end *		< I > hMax: maximum spacing allowable *		< I > rWanted: ideal ratio of one spacing to the next *		< O > rFound: actual ratio discovered *		< O > nSfound: number of start spaces *		< O > nMfound: number of maximum spaces * Returns:	OK / E_PRIVATE * Users:	MESHspacing * Calls:	oneSideRatio, stepsInSpan */static intmaxLimSpacing( width, hStart, hMax, rWanted, rFound, nSfound, nMfound )double width;double hStart, hMax;double rWanted, *rFound;int *nSfound, *nMfound;{  int nSpaceS;			/* Number of spaces at the start */  int nSpaceM;			/* Number of spaces with maximum size */  int nSpaceT;			/* Total number of spaces */  double dSpaceS;		/* Exact number of start spaces needed */  double dSpaceM;		/* Exact number of max spaces needed */  double dSpaceT;		/* Exact total number of spaces */  double rTempS;		/* For temporarily calc'ed ratio */  double remaining;		/* Width taken up by start spaces */  double rConnect, hBiggest;	/* Used to ensure ratio is valid */  double rSaveS = 0.0;		/* Saves best solution so far */  int nSaveS = 0;		/* " */  int nSaveM = 0;		/* " */  int i, j;			/* Searching indices */  int solnFound;		/* For partial search termination */  int solnError;		/* For partial search termination */  char errBuf[80];/* Compute the ratio needed to exactly go from hStart to hMax * in the given width.  If hMax is really big, then we know * the spaces can't exceed it. */  if ( width > hMax ) {    rTempS = 1.0 + (hMax - hStart)/(width - hMax);  }  else {    rTempS = 1.0e6;	 	/* an impossibly large value */  }  if (rWanted <= rTempS) { /* Spacings stay below maximum allowed */    dSpaceS = stepsInSpan( width, hStart, rWanted );    dSpaceM = 0.0;  }  else {/* Find number of spaces needed to increase hStart to hMax. */    dSpaceS = log(hMax/hStart)/log(rWanted);    remaining = hStart*geomSum(rWanted, dSpaceS);    dSpaceM = (width - remaining)/hMax;  }  dSpaceT = dSpaceS + dSpaceM;/* Search until an acceptable solution is found.  Some * cases may be repeated, but no harm is done. */  for (i = 0; i <= 1; i++) {    nSpaceT = (int)dSpaceT + i;/* Guess a starting point which is guaranteed to have a solution. */    nSpaceS = MIN( nSpaceT, MAX( 3, (int) dSpaceS) );    nSpaceM = nSpaceT - nSpaceS;    solnFound = solnError = FALSE;    while ( !solnFound ) {       remaining = width - hMax*nSpaceM;/* Test for the various special cases first. */      if ( nSpaceM < 0 || nSpaceS <= 0 ) {        solnError = TRUE;      }      else if (nSpaceS == 1) { /* check for exact fit */	if ( ABS(remaining - hStart) < 1.0e-3*hStart ) {	  hBiggest = hStart;          if (nSpaceM == 0) {            rTempS = 1.0;          }          else {            rTempS = hMax / hStart;          }	}	else {          solnError = TRUE;	}      }      else if (nSpaceS == 2) {	/* Easy to solve */	if (remaining > hStart) {	  hBiggest = remaining - hStart;	  rTempS = hBiggest / hStart;	}	else {          solnError = TRUE;	}      }      else {	if (remaining > hStart) {	  rTempS = rWanted;	  oneSideRatio( remaining, hStart, &rTempS, nSpaceS );	  hBiggest = hStart*pow(rTempS, (double)nSpaceS - 1.0);	}	else {          solnError = TRUE;	}      }      if ( solnError )	break;		/* while loop */      rConnect = hMax / hBiggest;      if ( rConnect < 1.0 - RAT_TOL ) {	nSpaceS--;	nSpaceM++;      }      else if ( (rConnect > rTempS + RAT_TOL) && nSpaceM != 0 ) {	nSpaceS++;	nSpaceM--;      }      else {	solnFound = TRUE;/* Save solution if it's better. */        if ( (rTempS >= 1.0 - RAT_TOL)	    && ABS(rWanted - rTempS) <= ABS(rWanted - rSaveS)) {	  rSaveS = rTempS;	  nSaveS = nSpaceS;	  nSaveM = nSpaceM;	}      }    }  }/* Prepare return values. */  if (rSaveS == 0.0) {    sprintf( errBuf,	"max-limited spacing can't find an acceptable solution\n");    SPfrontEnd->IFerror( ERR_WARNING, errBuf, NIL(IFuid) );    *rFound = 0.0;    *nSfound = *nMfound = 0;    return(E_PRIVATE);  }  else {    *rFound = rSaveS;    *nSfound = nSaveS;    *nMfound = nSaveM;    return(OK);  }}

⌨️ 快捷键说明

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