Copyright 1990 Regents of the University of California. All rights reserved.
Author: 1985 Thomas L. Quarles
**********/
* NIconvTest(ckt)
* perform the convergence test - returns 1 if any of the
* values in the old and new arrays have changed by more
* than absTol + relTol*(max(old,new)), otherwise returns 0
*/
#include "ngspice/ngspice.h"
#include "ngspice/cktdefs.h"
#include "ngspice/smpdefs.h"
extern bool ft_ngdebug;
int
NIconvTest(CKTcircuit *ckt)
{
int i;
int size;
CKTnode *node;
double old;
double new;
double tol;
static int nancount = 0;
node = ckt->CKTnodes;
size = SMPmatSize(ckt->CKTmatrix);
#ifdef STEPDEBUG
for (i=1;i<=size;i++) {
new = ckt->CKTrhs [i] ;
old = ckt->CKTrhsOld [i] ;
printf("chk for convergence: %s new: %g old: %g\n",CKTnodName(ckt,i),new,old);
}
#endif
for (i=1;i<=size;i++) {
node = node->next;
new = ckt->CKTrhs [i] ;
old = ckt->CKTrhsOld [i] ;
if (isnan(new)) {
if (ft_ngdebug && nancount < 10) {
fprintf(stderr, "Warning: non-convergence, node %s is nan\n", CKTnodName(ckt, i));
nancount++;
}
else if (ft_ngdebug && nancount == 10) {
fprintf(stderr, " non-convergence warnings (nan) limited to 10 node %s\n", CKTnodName(ckt, i));
nancount++;
}
return 1;
}
if(node->type == SP_VOLTAGE) {
tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) +
ckt->CKTvoltTol;
if (fabs(new-old) >tol ) {
#ifdef STEPDEBUG
printf(" non-convergence at node (type=3) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",CKTnodName(ckt,i),new,old,tol);
printf(" reltol: %g voltTol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + voltTol)\n",ckt->CKTreltol,ckt->CKTvoltTol);
#endif
ckt->CKTtroubleNode = i;
ckt->CKTtroubleElt = NULL;
return(1);
}
} else {
tol = ckt->CKTreltol * (MAX(fabs(old),fabs(new))) +
ckt->CKTabstol;
if (fabs(new-old) >tol ) {
#ifdef STEPDEBUG
printf(" non-convergence at node (type=%d) %s (fabs(new-old)>tol --> fabs(%g-%g)>%g)\n",node->type,CKTnodName(ckt,i),new,old,tol);
printf(" reltol: %g abstol: %g (tol=reltol*(MAX(fabs(old),fabs(new))) + abstol)\n",ckt->CKTreltol,ckt->CKTabstol);
#endif
ckt->CKTtroubleNode = i;
ckt->CKTtroubleElt = NULL;
return(1);
}
}
}
#ifdef NEWCONV
i = CKTconvTest(ckt);
if (i)
ckt->CKTtroubleNode = 0;
return(i);
#else
return(0);
#endif
}