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

📄 cktop.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
📖 第 1 页 / 共 2 页
字号:
/**********Copyright 1990 Regents of the University of California.  All rights reserved.Author: 1985 Thomas L. QuarlesModified: 2000  AlansFixesModified: 2005 Paolo Nenzi - Restructured**********/#include "ngspice.h"#include "cktdefs.h"#include "devdefs.h"#include "sperror.h"static int dynamic_gmin (CKTcircuit *, long int, long int, int);static int spice3_gmin (CKTcircuit *, long int, long int, int);static int gillespie_src (CKTcircuit *, long int, long int, int);static int spice3_src (CKTcircuit *, long int, long int, int);intCKTop (CKTcircuit * ckt, long int firstmode, long int continuemode,       int iterlim){  int converged;ckt->CKTmode = firstmode;  if (!ckt->CKTnoOpIter){#ifdef XSPICE/* gtri - begin - wbk - add convergence problem reporting flags */      if ((ckt->CKTnumGminSteps <= 0) && (ckt->CKTnumSrcSteps <= 0))          ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;      else	ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;/* gtri - end - wbk - add convergence problem reporting flags */#endif      converged = NIiter (ckt, iterlim);    } else {      converged = 1;		/* the 'go directly to gmin stepping' option */	}  if (converged != 0)    {      /* no convergence on the first try, so we do something else */      /* first, check if we should try gmin stepping */      if (ckt->CKTnumGminSteps >= 1){		if (ckt->CKTnumGminSteps == 1){			converged = dynamic_gmin(ckt, firstmode, continuemode, iterlim);			} else {			converged = spice3_gmin(ckt, firstmode, continuemode, iterlim);			}	}	if (!converged)		/* If gmin-stepping worked... move out */		return (0);	/* ... otherwise try stepping sources ...	 * now, we'll try source stepping - we scale the sources	 * to 0, converge, then start stepping them up until they	 * are at their normal values	 */	if (ckt->CKTnumSrcSteps >= 1){		if (ckt->CKTnumSrcSteps == 1) 			converged = gillespie_src(ckt, firstmode, continuemode, iterlim);			else			converged = spice3_src(ckt, firstmode, continuemode, iterlim);			}#ifdef XSPICE/* gtri - begin - wbk - add convergence problem reporting flags */	    ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;/* gtri - end - wbk - add convergence problem reporting flags */#endif			}      return (converged);    }/* CKTconvTest(ckt) *    this is a driver program to iterate through all the various *    convTest functions provided for the circuit elements in the *    given circuit  */intCKTconvTest (CKTcircuit * ckt){  extern SPICEdev **DEVices;  int i;  int error = OK;#ifdef PARALLEL_ARCH  int ibuf[2];  long type = MT_CONV, length = 2;#endif /* PARALLEL_ARCH */  for (i = 0; i < DEVmaxnum; i++)    {      if (((*DEVices[i]).DEVconvTest != NULL) && (ckt->CKThead[i] != NULL))	{	  error = (*((*DEVices[i]).DEVconvTest)) (ckt->CKThead[i], ckt);	}#ifdef PARALLEL_ARCH      if (error || ckt->CKTnoncon)	goto combine;#else      if (error)	return (error);      if (ckt->CKTnoncon)	{	  /* printf("convTest: device %s failed\n",	   * (*DEVices[i]).DEVpublic.name); */	  return (OK);	}#endif /* PARALLEL_ARCH */    }#ifdef PARALLEL_ARCHcombine:  /* See if any of the DEVconvTest functions bailed. If not, proceed. */  ibuf[0] = error;  ibuf[1] = ckt->CKTnoncon;  IGOP_ (&type, ibuf, &length, "+");  ckt->CKTnoncon = ibuf[1];  if (ibuf[0] != error)    {      error = E_MULTIERR;    }  return (error);#else  return (OK);#endif /* PARALLEL_ARCH */}/* Dynamic gmin stepping * Algorithm by Alan Gillespie * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) *  * return value: * 0 -> method converged * 1 -> method failed *  * Note that no path out of this code allows ckt->CKTdiagGmin to be  * anything but CKTgshunt. */static intdynamic_gmin (CKTcircuit * ckt, long int firstmode,	      long int continuemode, int iterlim){  double OldGmin, gtarget, factor;  int success, failed, converged;  int NumNodes, iters, i;  double *OldRhsOld, *OldCKTstate0;  CKTnode *n;  ckt->CKTmode = firstmode;  (*(SPfrontEnd->IFerror)) (ERR_INFO,			    "starting dynamic Gmin stepping", (IFuid *) NULL);  NumNodes = 0;  for (n = ckt->CKTnodes; n; n = n->next)	  NumNodes++;    OldRhsOld = (double *) MALLOC ((NumNodes + 1) * sizeof (double));  OldCKTstate0 =    (double *) MALLOC ((ckt->CKTnumStates + 1) * sizeof (double));  for (n = ckt->CKTnodes; n; n = n->next)	  *(ckt->CKTrhsOld + n->number) = 0;  for (i = 0; i < ckt->CKTnumStates; i++)	  *(ckt->CKTstate0 + i) = 0;      factor = ckt->CKTgminFactor;  OldGmin = 1e-2;  ckt->CKTdiagGmin = OldGmin / factor;  gtarget = MAX (ckt->CKTgmin, ckt->CKTgshunt);  success = failed = 0;  while ((!success) && (!failed)){	  fprintf (stderr, "\rTrying gmin = %12.4E ", ckt->CKTdiagGmin);      ckt->CKTnoncon = 1;      iters = ckt->CKTstat->STATnumIter;      converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);      iters = (ckt->CKTstat->STATnumIter) - iters;      if (converged == 0){		  ckt->CKTmode = continuemode;		  (*(SPfrontEnd->IFerror)) (ERR_INFO,			  "One successful Gmin step", (IFuid *) NULL);		  if (ckt->CKTdiagGmin <= gtarget){			success = 1;			} else {			  i = 0;			  for (n = ckt->CKTnodes; n; n = n->next){				OldRhsOld[i] = *(ckt->CKTrhsOld + n->number);				i++;				}					  for (i = 0; i < ckt->CKTnumStates; i++){				*(OldCKTstate0 + i) = *(ckt->CKTstate0 + i);				}			  if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){				factor *= sqrt (factor);				if (factor > ckt->CKTgminFactor)					factor = ckt->CKTgminFactor;				}			  if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4))				factor = sqrt (factor);					  OldGmin = ckt->CKTdiagGmin;			  if ((ckt->CKTdiagGmin) < (factor * gtarget)){				factor = ckt->CKTdiagGmin / gtarget;				ckt->CKTdiagGmin = gtarget;				} else {				  ckt->CKTdiagGmin /= factor;				}			}		} else {				  if (factor < 1.00005){			  failed = 1;			  (*(SPfrontEnd->IFerror)) (ERR_WARNING,					"Last gmin step failed",					(IFuid *) NULL);			} else {			  factor = sqrt (sqrt (factor));			  ckt->CKTdiagGmin = OldGmin / factor;			  i = 0;	      for (n = ckt->CKTnodes; n; n = n->next){			  *(ckt->CKTrhsOld + n->number) = OldRhsOld[i];			  i++;			}	      for (i = 0; i < ckt->CKTnumStates; i++){			  *(ckt->CKTstate0 + i) = *(OldCKTstate0 + i);				}			}		}		}	  ckt->CKTdiagGmin = ckt->CKTgshunt;  FREE (OldRhsOld);  FREE (OldCKTstate0);#ifdef XSPICE/* gtri - begin - wbk - add convergence problem reporting flags */  if (ckt->CKTnumSrcSteps <= 0)    ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;  else    ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;/* gtri - end - wbk - add convergence problem reporting flags */#endif    converged = NIiter (ckt, iterlim);  if (converged != 0){      (*(SPfrontEnd->IFerror)) (ERR_WARNING,				"Dynamic Gmin stepping failed",				(IFuid *) NULL);    } else {      (*(SPfrontEnd->IFerror)) (ERR_INFO,				"Dynamic Gmin stepping completed",				(IFuid *) NULL);#ifdef XSPICE/* gtri - begin - wbk - add convergence problem reporting flags */      ckt->enh->conv_debug.last_NIiter_call = MIF_FALSE;/* gtri - end - wbk - add convergence problem reporting flags */#endif    }  return (converged);}/* Spice3 gmin stepping * Modified 2000 - Alan Gillespie (added gshunt) * Modified 2005 - Paolo Nenzi (extracted from CKTop.c code) *  * return value: * 0 -> method converged * 1 -> method failed * * Note that no path out of this code allows ckt->CKTdiagGmin to be  * anything but CKTgshunt. */static intspice3_gmin (CKTcircuit * ckt, long int firstmode,	     long int continuemode, int iterlim){  int converged, i;  ckt->CKTmode = firstmode;  (*(SPfrontEnd->IFerror)) (ERR_INFO,			    "starting Gmin stepping", (IFuid *) NULL);  if (ckt->CKTgshunt == 0)	ckt->CKTdiagGmin = ckt->CKTgmin;	else 	ckt->CKTdiagGmin = ckt->CKTgshunt;  for (i = 0; i < ckt->CKTnumGminSteps; i++)	  ckt->CKTdiagGmin *= ckt->CKTgminFactor;      for (i = 0; i <= ckt->CKTnumGminSteps; i++){

⌨️ 快捷键说明

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