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

/**********
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);
}