You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
5.3 KiB
175 lines
5.3 KiB
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1985 Thomas L. Quarles
|
|
Modified 1999 Emmanuel Rouat
|
|
**********/
|
|
|
|
/*
|
|
* NIacIter(ckt)
|
|
*
|
|
* This subroutine performs the actual numerical iteration.
|
|
* It uses the sparse matrix stored in the NIstruct by NIinit,
|
|
* along with the matrix loading program, the load data, the
|
|
* convergence test function, and the convergence parameters
|
|
* - return value is non-zero for convergence failure
|
|
*/
|
|
|
|
#include "ngspice/ngspice.h"
|
|
#include "ngspice/trandefs.h"
|
|
#include "ngspice/cktdefs.h"
|
|
#include "ngspice/sperror.h"
|
|
|
|
#ifdef RFSPICE
|
|
// We don't need to reload the AC matrix for every port analysis
|
|
// So we split the NIacIter in two functions
|
|
int NIspPreload(CKTcircuit* ckt)
|
|
{
|
|
|
|
int error;
|
|
int ignore;
|
|
double startTime;
|
|
|
|
retry:
|
|
ckt->CKTnoncon = 0;
|
|
|
|
error = CKTacLoad(ckt);
|
|
|
|
if (error) return(error);
|
|
|
|
if (ckt->CKTniState & NIACSHOULDREORDER) {
|
|
startTime = SPfrontEnd->IFseconds();
|
|
error = SMPcReorder(ckt->CKTmatrix, ckt->CKTpivotAbsTol,
|
|
ckt->CKTpivotRelTol, &ignore);
|
|
ckt->CKTstat->STATreorderTime +=
|
|
SPfrontEnd->IFseconds() - startTime;
|
|
ckt->CKTniState &= ~NIACSHOULDREORDER;
|
|
if (error != 0) {
|
|
/* either singular equations or no memory, in either case,
|
|
* let caller handle problem
|
|
*/
|
|
|
|
int i, j ;
|
|
SMPgetError(ckt->CKTmatrix, &i, &j);
|
|
if(eq(NODENAME(ckt, i), NODENAME(ckt, j)))
|
|
SPfrontEnd->IFerrorf(ERR_WARNING, "singular matrix: check node %s\n", NODENAME(ckt, i));
|
|
else
|
|
SPfrontEnd->IFerrorf(ERR_WARNING, "singular matrix: check nodes %s and %s\n", NODENAME(ckt, i), NODENAME(ckt, j));
|
|
|
|
return(error);
|
|
}
|
|
}
|
|
else {
|
|
startTime = SPfrontEnd->IFseconds();
|
|
error = SMPcLUfac(ckt->CKTmatrix, ckt->CKTpivotAbsTol);
|
|
ckt->CKTstat->STATdecompTime +=
|
|
SPfrontEnd->IFseconds() - startTime;
|
|
if (error != 0) {
|
|
if (error == E_SINGULAR) {
|
|
/* the problem is that the matrix can't be solved with the
|
|
* current LU factorization. Maybe if we reload and
|
|
* try to reorder again it will help...
|
|
*/
|
|
|
|
int i, j ;
|
|
SMPgetError(ckt->CKTmatrix, &i, &j);
|
|
if(eq(NODENAME(ckt, i), NODENAME(ckt, j)))
|
|
SPfrontEnd->IFerrorf(ERR_WARNING, "singular matrix: check node %s\n", NODENAME(ckt, i));
|
|
else
|
|
SPfrontEnd->IFerrorf(ERR_WARNING, "singular matrix: check nodes %s and %s\n", NODENAME(ckt, i), NODENAME(ckt, j));
|
|
|
|
ckt->CKTniState |= NIACSHOULDREORDER;
|
|
goto retry;
|
|
}
|
|
return(error); /* can't handle E_BADMATRIX, so let caller */
|
|
}
|
|
}
|
|
|
|
return (OK);
|
|
};
|
|
|
|
int NIspSolve(CKTcircuit* ckt)
|
|
{
|
|
double startTime;
|
|
startTime = SPfrontEnd->IFseconds();
|
|
SMPcSolve(ckt->CKTmatrix, ckt->CKTrhs,
|
|
ckt->CKTirhs, ckt->CKTrhsSpare,
|
|
ckt->CKTirhsSpare);
|
|
ckt->CKTstat->STATsolveTime += SPfrontEnd->IFseconds() - startTime;
|
|
|
|
ckt->CKTrhs[0] = 0;
|
|
ckt->CKTrhsSpare[0] = 0;
|
|
ckt->CKTrhsOld[0] = 0;
|
|
ckt->CKTirhs[0] = 0;
|
|
ckt->CKTirhsSpare[0] = 0;
|
|
ckt->CKTirhsOld[0] = 0;
|
|
|
|
SWAP(double*, ckt->CKTirhs, ckt->CKTirhsOld);
|
|
|
|
SWAP(double*, ckt->CKTrhs, ckt->CKTrhsOld);
|
|
return (OK);
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
NIacIter(CKTcircuit *ckt)
|
|
{
|
|
int error;
|
|
int ignore;
|
|
double startTime;
|
|
|
|
retry:
|
|
ckt->CKTnoncon=0;
|
|
|
|
error = CKTacLoad(ckt);
|
|
if(error) return(error);
|
|
|
|
if(ckt->CKTniState & NIACSHOULDREORDER) {
|
|
startTime = SPfrontEnd->IFseconds();
|
|
error = SMPcReorder(ckt->CKTmatrix,ckt->CKTpivotAbsTol,
|
|
ckt->CKTpivotRelTol,&ignore);
|
|
ckt->CKTstat->STATreorderTime +=
|
|
SPfrontEnd->IFseconds()- startTime;
|
|
ckt->CKTniState &= ~NIACSHOULDREORDER;
|
|
if(error != 0) {
|
|
/* either singular equations or no memory, in either case,
|
|
* let caller handle problem
|
|
*/
|
|
return(error);
|
|
}
|
|
} else {
|
|
startTime = SPfrontEnd->IFseconds();
|
|
error = SMPcLUfac(ckt->CKTmatrix,ckt->CKTpivotAbsTol);
|
|
ckt->CKTstat->STATdecompTime +=
|
|
SPfrontEnd->IFseconds()-startTime;
|
|
if(error != 0) {
|
|
if(error == E_SINGULAR) {
|
|
/* the problem is that the matrix can't be solved with the
|
|
* current LU factorization. Maybe if we reload and
|
|
* try to reorder again it will help...
|
|
*/
|
|
ckt->CKTniState |= NIACSHOULDREORDER;
|
|
goto retry;
|
|
}
|
|
return(error); /* can't handle E_BADMATRIX, so let caller */
|
|
}
|
|
}
|
|
startTime = SPfrontEnd->IFseconds();
|
|
SMPcSolve(ckt->CKTmatrix,ckt->CKTrhs,
|
|
ckt->CKTirhs, ckt->CKTrhsSpare,
|
|
ckt->CKTirhsSpare);
|
|
ckt->CKTstat->STATsolveTime += SPfrontEnd->IFseconds() - startTime;
|
|
|
|
ckt->CKTrhs[0] = 0;
|
|
ckt->CKTrhsSpare[0] = 0;
|
|
ckt->CKTrhsOld[0] = 0;
|
|
ckt->CKTirhs[0] = 0;
|
|
ckt->CKTirhsSpare[0] = 0;
|
|
ckt->CKTirhsOld[0] = 0;
|
|
|
|
SWAP(double *, ckt->CKTirhs, ckt->CKTirhsOld);
|
|
|
|
SWAP(double *, ckt->CKTrhs, ckt->CKTrhsOld);
|
|
|
|
return(OK);
|
|
}
|