コード例 #1
0
ファイル: cktop.c プロジェクト: OS2World/APP-SCIENCE-NGSpice
/* Spice3 Source stepping
 * 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->CKTsrcFact to be 
 * anything but 1.00000.
 */
static int
spice3_src (CKTcircuit * ckt, long int firstmode,
	    long int continuemode, int iterlim)
{

  int converged, i;

  ckt->CKTmode = firstmode;
  (*(SPfrontEnd->IFerror)) (ERR_INFO,
			    "Starting source stepping", (IFuid *) NULL);

  for (i = 0; i <= ckt->CKTnumSrcSteps; i++)
    {
      ckt->CKTsrcFact = ((double) i) / ((double) ckt->CKTnumSrcSteps);
#ifdef XSPICE
/* gtri - begin - wbk - add convergence problem reporting flags */
      ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
/* gtri - end - wbk - add convergence problem reporting flags */
#endif
      converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
      ckt->CKTmode = continuemode;
      if (converged != 0)
	{
	  ckt->CKTsrcFact = 1;
	  ckt->CKTcurrentAnalysis = DOING_TRAN;
	  (*(SPfrontEnd->IFerror)) (ERR_WARNING,
				    "source stepping failed", (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);
	}
      (*(SPfrontEnd->IFerror)) (ERR_INFO,
				"One successful source step", (IFuid *) NULL);
    }
  (*(SPfrontEnd->IFerror)) (ERR_INFO,
			    "Source stepping completed", (IFuid *) NULL);
  ckt->CKTsrcFact = 1;
#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 (0);
}
コード例 #2
0
int
DCtrCurv(CKTcircuit *ckt, int restart)
{
    TRCV *job = (TRCV *) ckt->CKTcurJob;

    int i;
    double *temp;
    int converged;
    int rcode;
    int vcode;
    int icode;
    int j;
    int error;
    IFuid varUid;
    IFuid *nameList;
    int numNames;
    int firstTime = 1;
    static runDesc *plot = NULL;

#ifdef WANT_SENSE2
    long save;
#ifdef SENSDEBUG
    if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) {
        printf("\nDC Sensitivity Results\n\n");
        CKTsenPrint(ckt);
    }
#endif
#endif

    rcode = CKTtypelook("Resistor");
    vcode = CKTtypelook("Vsource");
    icode = CKTtypelook("Isource");

    if (!restart && job->TRCVnestState >= 0) {
        /* continuing */
        i = job->TRCVnestState;
        /* resume to work? saj*/
        error = SPfrontEnd->OUTpBeginPlot (NULL, NULL,
                                           NULL,
                                           NULL, 0,
                                           666, NULL, 666,
                                           &plot);
        goto resume;
    }

    ckt->CKTtime = 0;
    ckt->CKTdelta = job->TRCVvStep[0];
    ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
    ckt->CKTorder = 1;

    /* Save the state of the circuit */
    for (j = 0; j < 7; j++)
        ckt->CKTdeltaOld[j] = ckt->CKTdelta;

    for (i = 0; i <= job->TRCVnestLevel; i++) {

        if (rcode >= 0) {
            /* resistances are in this version, so use them */
            RESinstance *here;
            RESmodel *model;

            for (model = (RESmodel *)ckt->CKThead[rcode]; model; model = model->RESnextModel)
                for (here = model->RESinstances; here; here = here->RESnextInstance)
                    if (here->RESname == job->TRCVvName[i]) {
                        job->TRCVvElt[i]  = (GENinstance *)here;
                        job->TRCVvSave[i] = here->RESresist;
                        job->TRCVgSave[i] = here->RESresGiven;
                        job->TRCVvType[i] = rcode;
                        here->RESresist   = job->TRCVvStart[i];
                        here->RESresGiven = 1;
                        CKTtemp(ckt);
                        goto found;
                    }
        }

        if (vcode >= 0) {
            /* voltage sources are in this version, so use them */
            VSRCinstance *here;
            VSRCmodel *model;

            for (model = (VSRCmodel *)ckt->CKThead[vcode]; model; model = model->VSRCnextModel)
                for (here = model->VSRCinstances; here; here = here->VSRCnextInstance)
                    if (here->VSRCname == job->TRCVvName[i]) {
                        job->TRCVvElt[i]  = (GENinstance *)here;
                        job->TRCVvSave[i] = here->VSRCdcValue;
                        job->TRCVgSave[i] = here->VSRCdcGiven;
                        job->TRCVvType[i] = vcode;
                        here->VSRCdcValue = job->TRCVvStart[i];
                        here->VSRCdcGiven = 1;
                        goto found;
                    }
        }

        if (icode >= 0) {
            /* current sources are in this version, so use them */
            ISRCinstance *here;
            ISRCmodel *model;

            for (model = (ISRCmodel *)ckt->CKThead[icode]; model; model = model->ISRCnextModel)
                for (here = model->ISRCinstances; here; here = here->ISRCnextInstance)
                    if (here->ISRCname == job->TRCVvName[i]) {
                        job->TRCVvElt[i]  = (GENinstance *)here;
                        job->TRCVvSave[i] = here->ISRCdcValue;
                        job->TRCVgSave[i] = here->ISRCdcGiven;
                        job->TRCVvType[i] = icode;
                        here->ISRCdcValue = job->TRCVvStart[i];
                        here->ISRCdcGiven = 1;
                        goto found;
                    }
        }

        if (!strcmp(job->TRCVvName[i], "temp")) {
            job->TRCVvSave[i] = ckt->CKTtemp; /* Saves the old circuit temperature */
            job->TRCVvType[i] = TEMP_CODE;    /* Set the sweep type code */
            ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK; /* Set the new circuit temp */
            if (expr_w_temper)
                inp_evaluate_temper();
            CKTtemp(ckt);
            goto found;
        }

        SPfrontEnd->IFerrorf (ERR_FATAL,
                              "DCtrCurv: source / resistor %s not in circuit", job->TRCVvName[i]);
        return(E_NODEV);

    found:;
    }

#ifdef HAS_PROGREP
    actval = job->TRCVvStart[job->TRCVnestLevel];
    actdiff = job->TRCVvStart[job->TRCVnestLevel] - job->TRCVvStop[job->TRCVnestLevel];
#endif

#ifdef XSPICE
/* gtri - add - wbk - 12/19/90 - Add IPC stuff and anal_init and anal_type */

    /* Tell the beginPlot routine what mode we're in */
    g_ipc.anal_type = IPC_ANAL_DCTRCURVE;

    /* Tell the code models what mode we're in */
    g_mif_info.circuit.anal_type = MIF_DC;

    g_mif_info.circuit.anal_init = MIF_TRUE;

/* gtri - end - wbk */
#endif

    error = CKTnames(ckt, &numNames, &nameList);
    if (error)
        return(error);

    i = job->TRCVnestLevel;

    if (job->TRCVvType[i] == vcode)
        SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "v-sweep", UID_OTHER, NULL);
    else if (job->TRCVvType[i] == icode)
        SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "i-sweep", UID_OTHER, NULL);
    else if (job->TRCVvType[i] == TEMP_CODE)
        SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "temp-sweep", UID_OTHER, NULL);
    else if (job->TRCVvType[i] == rcode)
        SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "res-sweep", UID_OTHER, NULL);
    else
        SPfrontEnd->IFnewUid (ckt, &varUid, NULL, "?-sweep", UID_OTHER, NULL);

    error = SPfrontEnd->OUTpBeginPlot (ckt, ckt->CKTcurJob,
                                       ckt->CKTcurJob->JOBname,
                                       varUid, IF_REAL,
                                       numNames, nameList, IF_REAL,
                                       &plot);
    tfree(nameList);

    if (error)
        return(error);

    /* initialize CKTsoaCheck `warn' counters */
    if (ckt->CKTsoaCheck)
        error = CKTsoaInit();

    /* now have finished the initialization - can start doing hard part */

    i = 0;

 resume:

    for (;;) {

        if (job->TRCVvType[i] == vcode) { /* voltage source */
            if (SGN(job->TRCVvStep[i]) *
                (((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue -
                 job->TRCVvStop[i]) >
                DBL_EPSILON * 1e+03)
            {
                i++;
                firstTime = 1;
                ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
                if (i > job->TRCVnestLevel)
                    break;
                goto nextstep;
            }
        } else if (job->TRCVvType[i] == icode) { /* current source */
            if (SGN(job->TRCVvStep[i]) *
                (((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue -
                 job->TRCVvStop[i]) >
                DBL_EPSILON * 1e+03)
            {
                i++;
                firstTime = 1;
                ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
                if (i > job->TRCVnestLevel)
                    break;
                goto nextstep;
            }
        } else if (job->TRCVvType[i] == rcode) { /* resistance */
            if (SGN(job->TRCVvStep[i]) *
                (((RESinstance*)(job->TRCVvElt[i]))->RESresist -
                 job->TRCVvStop[i]) >
                DBL_EPSILON * 1e+03)
            {
                i++;
                firstTime = 1;
                ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
                if (i > job->TRCVnestLevel)
                    break;
                goto nextstep;
            }
        } else if (job->TRCVvType[i] == TEMP_CODE) { /* temp sweep */
            if (SGN(job->TRCVvStep[i]) *
                ((ckt->CKTtemp - CONSTCtoK) - job->TRCVvStop[i]) >
                DBL_EPSILON * 1e+03)
            {
                i++;
                firstTime = 1;
                ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT;
                if (i > job->TRCVnestLevel)
                    break;
                goto nextstep;
            }
        }

        while (--i >= 0)
            if (job->TRCVvType[i] == vcode) { /* voltage source */
                ((VSRCinstance *)(job->TRCVvElt[i]))->VSRCdcValue =
                    job->TRCVvStart[i];
            } else if (job->TRCVvType[i] == icode) { /* current source */
                ((ISRCinstance *)(job->TRCVvElt[i]))->ISRCdcValue =
                    job->TRCVvStart[i];
            } else if (job->TRCVvType[i] == TEMP_CODE) {
                ckt->CKTtemp = job->TRCVvStart[i] + CONSTCtoK;
                if (expr_w_temper)
                    inp_evaluate_temper();
                CKTtemp(ckt);
            } else if (job->TRCVvType[i] == rcode) {
                ((RESinstance *)(job->TRCVvElt[i]))->RESresist =
                    job->TRCVvStart[i];
                /* RESload() needs conductance as well */
                ((RESinstance *)(job->TRCVvElt[i]))->RESconduct =
                    1 / (((RESinstance *)(job->TRCVvElt[i]))->RESresist);
                DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
            }

        /* Rotate state vectors. */
        temp = ckt->CKTstates[ckt->CKTmaxOrder + 1];
        for (j = ckt->CKTmaxOrder; j >= 0; j--)
            ckt->CKTstates[j + 1] = ckt->CKTstates[j];
        ckt->CKTstate0 = temp;

        /* do operation */
#ifdef XSPICE
/* gtri - begin - wbk - Do EVTop if event instances exist */
        if (ckt->evt->counts.num_insts == 0) {
            /* If no event-driven instances, do what SPICE normally does */
#endif
            converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter);
            if (converged != 0) {
                converged = CKTop(ckt,
                                  (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT,
                                  (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT,
                                  ckt->CKTdcMaxIter);
                if (converged != 0)
                    return(converged);
            }
#ifdef XSPICE
        }
        else {
            /* else do new algorithm */

            /* first get the current step in the analysis */
            if (job->TRCVvType[0] == vcode) {
                g_mif_info.circuit.evt_step =
                    ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue;
            } else if (job->TRCVvType[0] == icode) {
                g_mif_info.circuit.evt_step =
                    ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue;
            } else if (job->TRCVvType[0] == rcode) {
                g_mif_info.circuit.evt_step =
                    ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist;
            } else if (job->TRCVvType[0] == TEMP_CODE) {
                g_mif_info.circuit.evt_step =
                    ckt->CKTtemp - CONSTCtoK;
            }

            /* if first time through, call EVTop immediately and save event results */
            if (firstTime) {
                converged = EVTop(ckt,
                                  (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT,
                                  (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT,
                                  ckt->CKTdcMaxIter,
                                  MIF_TRUE);
                EVTdump(ckt, IPC_ANAL_DCOP, g_mif_info.circuit.evt_step);
                EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step);
                if (converged != 0)
                    return(converged);
            }
            /* else, call NIiter first with mode = MODEINITPRED */
            /* to attempt quick analog solution.  Then call all hybrids and call */
            /* EVTop only if event outputs have changed, or if non-converged */
            else {
                converged = NIiter(ckt, ckt->CKTdcTrcvMaxIter);
                EVTcall_hybrids(ckt);
                if ((converged != 0) || (ckt->evt->queue.output.num_changed != 0)) {
                    converged = EVTop(ckt,
                                      (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITJCT,
                                      (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITFLOAT,
                                      ckt->CKTdcMaxIter,
                                      MIF_FALSE);
                    EVTdump(ckt, IPC_ANAL_DCTRCURVE, g_mif_info.circuit.evt_step);
                    EVTop_save(ckt, MIF_FALSE, g_mif_info.circuit.evt_step);
                    if (converged != 0)
                        return(converged);
                }
            }
        }
/* gtri - end - wbk - Do EVTop if event instances exist */
#endif

        ckt->CKTmode = (ckt->CKTmode & MODEUIC) | MODEDCTRANCURVE | MODEINITPRED;
        if (job->TRCVvType[0] == vcode)
            ckt->CKTtime = ((VSRCinstance *)(job->TRCVvElt[0]))->VSRCdcValue;
        else if (job->TRCVvType[0] == icode)
            ckt->CKTtime = ((ISRCinstance *)(job->TRCVvElt[0]))->ISRCdcValue;
        else if (job->TRCVvType[0] == rcode)
            ckt->CKTtime = ((RESinstance *)(job->TRCVvElt[0]))->RESresist;
        else if (job->TRCVvType[0] == TEMP_CODE)
            ckt->CKTtime = ckt->CKTtemp - CONSTCtoK;

#ifdef XSPICE
/* gtri - add - wbk - 12/19/90 - Add IPC stuff */

        /* If first time through, call CKTdump to output Operating Point info */
        /* for Mspice compatibility */

        if (g_ipc.enabled && firstTime) {
            ipc_send_dcop_prefix();
            CKTdump(ckt, 0.0, plot);
            ipc_send_dcop_suffix();
        }

/* gtri - end - wbk */
#endif

#ifdef WANT_SENSE2
/*
  if (!ckt->CKTsenInfo) printf("sensitivity structure does not exist\n");
*/
        if (ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & DCSEN)) {
            int senmode;

#ifdef SENSDEBUG
            if (job->TRCVvType[0] == vcode) { /* voltage source */
                printf("Voltage Source Value : %.5e V\n",
                       ((VSRCinstance*) (job->TRCVvElt[0]))->VSRCdcValue);
            }
            if (job->TRCVvType[0] == icode) { /* current source */
                printf("Current Source Value : %.5e A\n",
                       ((ISRCinstance*)(job->TRCVvElt[0]))->ISRCdcValue);
            }
            if (job->TRCVvType[0] == rcode) { /* resistance */
                printf("Current Resistance Value : %.5e Ohm\n",
                       ((RESinstance*)(job->TRCVvElt[0]->GENmodPtr))->RESresist);
            }
            if (job->TRCVvType[0] == TEMP_CODE) { /* Temperature */
                printf("Current Circuit Temperature : %.5e C\n",
                       ckt->CKTtemp - CONSTCtoK);
            }
#endif

            senmode = ckt->CKTsenInfo->SENmode;
            save = ckt->CKTmode;
            ckt->CKTsenInfo->SENmode = DCSEN;
            error = CKTsenDCtran(ckt);
            if (error)
                return(error);

            ckt->CKTmode = save;
            ckt->CKTsenInfo->SENmode = senmode;
        }
#endif

#ifdef XSPICE
/* gtri - modify - wbk - 12/19/90 - Send IPC delimiters */

        if (g_ipc.enabled)
            ipc_send_data_prefix(ckt->CKTtime);
#endif

        CKTdump(ckt,ckt->CKTtime,plot);

        if (ckt->CKTsoaCheck)
            error = CKTsoaCheck(ckt);

#ifdef XSPICE
        if (g_ipc.enabled)
            ipc_send_data_suffix();

/* gtri - end - wbk */
#endif

        if (firstTime) {
            firstTime = 0;
            memcpy(ckt->CKTstate1, ckt->CKTstate0,
                   (size_t) ckt->CKTnumStates * sizeof(double));
        }

        i = 0;

    nextstep:;

        if (job->TRCVvType[i] == vcode) { /* voltage source */
            ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue +=
                job->TRCVvStep[i];
        } else if (job->TRCVvType[i] == icode) { /* current source */
            ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue +=
                job->TRCVvStep[i];
        } else if (job->TRCVvType[i] == rcode) { /* resistance */
            ((RESinstance*)(job->TRCVvElt[i]))->RESresist +=
                job->TRCVvStep[i];
            /* RESload() needs conductance as well */
            ((RESinstance*)(job->TRCVvElt[i]))->RESconduct =
                1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist);
            DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
        } else if (job->TRCVvType[i] == TEMP_CODE) { /* temperature */
            ckt->CKTtemp += job->TRCVvStep[i];
            if (expr_w_temper)
                inp_evaluate_temper();
            CKTtemp(ckt);
        }

        if (SPfrontEnd->IFpauseTest()) {
            /* user asked us to pause, so save state */
            job->TRCVnestState = i;
            return(E_PAUSE);
        }

#ifdef HAS_PROGREP
        if (i == job->TRCVnestLevel) {
            actval += job->TRCVvStep[job->TRCVnestLevel];
            SetAnalyse("dc", abs((int)(actval * 1000. / actdiff)));
        }
#endif

    }

    /* all done, lets put everything back */

    for (i = 0; i <= job->TRCVnestLevel; i++)
        if (job->TRCVvType[i] == vcode) {   /* voltage source */
            ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcValue = job->TRCVvSave[i];
            ((VSRCinstance*)(job->TRCVvElt[i]))->VSRCdcGiven = (job->TRCVgSave[i] != 0);
        } else  if (job->TRCVvType[i] == icode) { /*current source */
            ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcValue = job->TRCVvSave[i];
            ((ISRCinstance*)(job->TRCVvElt[i]))->ISRCdcGiven = (job->TRCVgSave[i] != 0);
        } else  if (job->TRCVvType[i] == rcode) { /* Resistance */
            ((RESinstance*)(job->TRCVvElt[i]))->RESresist = job->TRCVvSave[i];
            /* RESload() needs conductance as well */
            ((RESinstance*)(job->TRCVvElt[i]))->RESconduct =
                1 / (((RESinstance*)(job->TRCVvElt[i]))->RESresist);
            ((RESinstance*)(job->TRCVvElt[i]))->RESresGiven = (job->TRCVgSave[i] != 0);
            DEVices[rcode]->DEVload(job->TRCVvElt[i]->GENmodPtr, ckt);
        } else if (job->TRCVvType[i] == TEMP_CODE) {
            ckt->CKTtemp = job->TRCVvSave[i];
            if (expr_w_temper)
                inp_evaluate_temper();
            CKTtemp(ckt);
        }

    SPfrontEnd->OUTendPlot (plot);

    return(OK);
}
コード例 #3
0
ファイル: cktop.c プロジェクト: OS2World/APP-SCIENCE-NGSpice
/* Gillespie's Source stepping
 * 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->CKTsrcFact to be 
 * anything but 1.00000.
 */
static int
gillespie_src (CKTcircuit * ckt, long int firstmode,
	       long int continuemode, int iterlim)
{

  int converged, NumNodes, i, iters;
  double raise, ConvFact;
  double *OldRhsOld, *OldCKTstate0;
  CKTnode *n;

  ckt->CKTmode = firstmode;
  (*(SPfrontEnd->IFerror)) (ERR_INFO,
			    "Starting source stepping", (IFuid *) NULL);

  ckt->CKTsrcFact = 0;
  raise = 0.001;
  ConvFact = 0;

  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;

/*  First, try a straight solution with all sources at zero */

  fprintf (stderr, "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);
  converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);

/*  If this doesn't work, try gmin stepping as well for the first solution */

  if (converged != 0){
      fprintf (stderr, "\n");
      if (ckt->CKTgshunt <= 0){
		  ckt->CKTdiagGmin = ckt->CKTgmin;
	} else {
		  ckt->CKTdiagGmin = ckt->CKTgshunt;
	}
	
      for (i = 0; i < 10; i++)
		  ckt->CKTdiagGmin *= 10;

      for (i = 0; i <= 10; i++){
		  fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
		  ckt->CKTnoncon = 1;

#ifdef XSPICE
/* gtri - begin - wbk - add convergence problem reporting flags */
      ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
/* gtri - end - wbk - add convergence problem reporting flags */
#endif	  

		  converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);

	  if (converged != 0){
	      ckt->CKTdiagGmin = ckt->CKTgshunt;
	      (*(SPfrontEnd->IFerror)) (ERR_WARNING,
					"gmin step failed", (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
	      break;
	  }

	  ckt->CKTdiagGmin /= 10;
	  ckt->CKTmode = continuemode;
	  (*(SPfrontEnd->IFerror)) (ERR_INFO,
				    "One successful gmin step",
				    (IFuid *) NULL);
      }
      ckt->CKTdiagGmin = ckt->CKTgshunt;
  }

/*  If we've got convergence, then try stepping up the sources  */

  if (converged == 0){
	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);
	

      (*(SPfrontEnd->IFerror)) (ERR_INFO,
				"One successful source step", (IFuid *) NULL);
      ckt->CKTsrcFact = ConvFact + raise;	
  }


  if (converged == 0)
    do {
	fprintf (stderr,
		 "Supplies reduced to %8.4f%% ", ckt->CKTsrcFact * 100);

	iters = ckt->CKTstat->STATnumIter;

#ifdef XSPICE
/* gtri - begin - wbk - add convergence problem reporting flags */
      ckt->enh->conv_debug.last_NIiter_call = MIF_TRUE;
/* gtri - end - wbk - add convergence problem reporting flags */
#endif	  
	converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);
	  
	iters = (ckt->CKTstat->STATnumIter) - iters;

	ckt->CKTmode = continuemode;

	if (converged == 0){
	    ConvFact = ckt->CKTsrcFact;
	    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);

	    (*(SPfrontEnd->IFerror)) (ERR_INFO,
				      "One successful source step",
				      (IFuid *) NULL);

	    ckt->CKTsrcFact = ConvFact + raise;

	    if (iters <= (ckt->CKTdcTrcvMaxIter / 4)){
			raise = raise * 1.5;
		}

	    if (iters > (3 * ckt->CKTdcTrcvMaxIter / 4)){
			raise = raise * 0.5;
		}

/*                    if (raise>0.01) raise=0.01; */

	} else {

	    if ((ckt->CKTsrcFact - ConvFact) < 1e-8)
	      break;

	    raise = raise / 10;

	    if (raise > 0.01)
	      raise = 0.01;

	    ckt->CKTsrcFact = ConvFact;
	    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);
	      
	  }

	if ((ckt->CKTsrcFact) > 1)
	  ckt->CKTsrcFact = 1;

      }
	while ((raise >= 1e-7) && (ConvFact < 1));

  FREE (OldRhsOld);
  FREE (OldCKTstate0);
  ckt->CKTsrcFact = 1;

  if (ConvFact != 1)
    {
      ckt->CKTsrcFact = 1;
      ckt->CKTcurrentAnalysis = DOING_TRAN;
      (*(SPfrontEnd->IFerror)) (ERR_WARNING,
				"source stepping failed", (IFuid *) NULL);
      return (E_ITERLIM);
    }
  else
    {
      (*(SPfrontEnd->IFerror)) (ERR_INFO,
				"Source stepping completed", (IFuid *) NULL);
      return (0);
    }
}
コード例 #4
0
ファイル: cktop.c プロジェクト: OS2World/APP-SCIENCE-NGSpice
static int
spice3_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++){
      fprintf (stderr, "Trying gmin = %12.4E ", ckt->CKTdiagGmin);
      ckt->CKTnoncon = 1;
      converged = NIiter (ckt, ckt->CKTdcTrcvMaxIter);

      if (converged != 0){
		  ckt->CKTdiagGmin = ckt->CKTgshunt;
		  (*(SPfrontEnd->IFerror)) (ERR_WARNING,
				    "gmin step failed", (IFuid *) NULL);
		  break;
      }

      ckt->CKTdiagGmin /= ckt->CKTgminFactor;
      ckt->CKTmode = continuemode;

      (*(SPfrontEnd->IFerror)) (ERR_INFO,
				"One successful gmin step", (IFuid *) NULL);
  }

  ckt->CKTdiagGmin = ckt->CKTgshunt;

#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_INFO,
		"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

    } else {
      (*(SPfrontEnd->IFerror)) (ERR_WARNING,
				"gmin stepping failed", (IFuid *) NULL);
    }

  return (converged);

}
コード例 #5
0
ファイル: cktop.c プロジェクト: OS2World/APP-SCIENCE-NGSpice
int
CKTop (CKTcircuit * ckt, long int firstmode, long int continuemode,
       int iterlim)
{
  int converged;
#ifdef HAS_WINDOWS
        SetAnalyse("op", 0);
#endif
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);
    
}
コード例 #6
0
ファイル: cktop.c プロジェクト: OS2World/APP-SCIENCE-NGSpice
static int
dynamic_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, "Trying 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 {
			(*(SPfrontEnd->IFerror)) (ERR_WARNING,
					"Further gmin increment",
					(IFuid *) NULL);
			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);
}