mirror of
https://git.code.sf.net/p/ngspice/ngspice
synced 2026-08-22 13:57:32 +02:00
Enable CIDER with KLU for DC, OP, and TRAN analyses. Small signal AC analysis is not yet supported for CIDER complex valued device KLU matrices. The examples/cider testcases produce printed simulation result values which have slight differences between Sparse and KLU. Differences are probably expected and in a few cases are ~1-2%, sometimes a little more. This should be good enough for most CIDER analyses. Francesco did a good piece of work. Runtimes are significantly shorter with KLU.
This commit is contained in:
committed by
Holger Vogt
parent
20561d309d
commit
7af862af3d
@@ -14,6 +14,8 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
#include "ngspice/complex.h"
|
||||
#include "ngspice/spmatrix.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/ftedefs.h"
|
||||
|
||||
#include "onedext.h"
|
||||
#include "oneddefs.h"
|
||||
@@ -29,7 +31,17 @@ extern IFfrontEnd *SPfrontEnd;
|
||||
*/
|
||||
SPcomplex yAc;
|
||||
|
||||
|
||||
#ifdef KLU
|
||||
static void small_signal_check(char *where)
|
||||
{
|
||||
if (ft_curckt->ci_ckt->CKTmode == MODEAC
|
||||
|| ft_curckt->ci_ckt->CKTmode == MODEACNOISE) {
|
||||
fprintf(stderr, "Error: CIDER %s small signal simulation is not (yet) supported with 'option klu'.\n", where);
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
controlled_exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
|
||||
@@ -45,6 +57,11 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
|
||||
bool SORFailed;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMDadmittance");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Each time we call this counts as one AC iteration. */
|
||||
pDevice->pStats->numIters[STAT_AC] += 1;
|
||||
@@ -119,6 +136,7 @@ NUMDadmittance(ONEdevice *pDevice, double omega, SPcomplex *yd)
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
// Not implemented
|
||||
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
|
||||
} else {
|
||||
#endif
|
||||
@@ -196,6 +214,11 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce,
|
||||
SPcomplex cOmega, pIeVce, pIcVce, pIeVbe, pIcVbe;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NBJTadmittance");
|
||||
}
|
||||
#endif
|
||||
/* Each time we call this counts as one AC iteration. */
|
||||
pDevice->pStats->numIters[STAT_AC] += 1;
|
||||
|
||||
@@ -315,6 +338,7 @@ NBJTadmittance(ONEdevice *pDevice, double omega, SPcomplex *yIeVce,
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
// Not implemented
|
||||
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
|
||||
} else {
|
||||
#endif
|
||||
@@ -552,6 +576,11 @@ NUMDys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yd)
|
||||
SPcomplex *y;
|
||||
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMDys");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* change context names of solution vectors for ac analysis dcDeltaSolution
|
||||
* stores the real part and copiedSolution stores the imaginary part of the
|
||||
@@ -580,6 +609,7 @@ NUMDys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yd)
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
// Not implemented
|
||||
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
|
||||
} else {
|
||||
#endif
|
||||
@@ -640,6 +670,11 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce,
|
||||
SPcomplex temp, cOmega;
|
||||
SPcomplex pIeVce, pIcVce, pIeVbe, pIcVbe;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NBJTys");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* change context names of solution vectors for ac analysis dcDeltaSolution
|
||||
* stores the real part and copiedSolution stores the imaginary part of the
|
||||
@@ -667,6 +702,7 @@ NBJTys(ONEdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce,
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
// Not implemented
|
||||
pDevice->matrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex ;
|
||||
} else {
|
||||
#endif
|
||||
|
||||
@@ -16,6 +16,9 @@ Author: 1987 Kartikeya Mayaram, U. C. Berkeley CAD Group
|
||||
#include "ngspice/bool.h"
|
||||
#include "ngspice/macros.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "ngspice/cktdefs.h"
|
||||
#include "ngspice/ftedefs.h"
|
||||
|
||||
#include "twoddefs.h"
|
||||
#include "twodext.h"
|
||||
#include "ngspice/cidersupt.h"
|
||||
@@ -28,6 +31,18 @@ extern IFfrontEnd *SPfrontEnd;
|
||||
*/
|
||||
SPcomplex yTotal;
|
||||
|
||||
#ifdef KLU
|
||||
static void small_signal_check(char *where)
|
||||
{
|
||||
if (ft_curckt->ci_ckt->CKTmode == MODEAC
|
||||
|| ft_curckt->ci_ckt->CKTmode == MODEACNOISE) {
|
||||
fprintf(stderr, "Error: CIDER %s small signal simulation is not (yet) supported with 'option klu'.\n", where);
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
controlled_exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd)
|
||||
{
|
||||
@@ -42,6 +57,11 @@ NUMD2admittance(TWOdevice *pDevice, double omega, SPcomplex *yd)
|
||||
bool SORFailed;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMD2admittance");
|
||||
}
|
||||
#endif
|
||||
/* Each time we call this counts as one AC iteration. */
|
||||
pDevice->pStats->numIters[STAT_AC] += 1;
|
||||
|
||||
@@ -192,6 +212,11 @@ NBJT2admittance(TWOdevice *pDevice, double omega, SPcomplex *yIeVce,
|
||||
SPcomplex cOmega;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NBJT2admittance");
|
||||
}
|
||||
#endif
|
||||
/* Each time we call this counts as one AC iteration. */
|
||||
pDevice->pStats->numIters[STAT_AC] += 1;
|
||||
|
||||
@@ -416,6 +441,11 @@ NUMOSadmittance(TWOdevice *pDevice, double omega, struct mosAdmittances *yAc)
|
||||
SPcomplex *y, cOmega;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMOSadmittance");
|
||||
}
|
||||
#endif
|
||||
/* Each time we call this counts as one AC iteration. */
|
||||
pDevice->pStats->numIters[STAT_AC] += 1;
|
||||
|
||||
@@ -1151,6 +1181,11 @@ NUMD2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIn)
|
||||
bool deltaVContact = FALSE;
|
||||
SPcomplex temp, cOmega;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMD2ys");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* change context names of solution vectors for ac analysis dcDeltaSolution
|
||||
* stores the real part and copiedSolution stores the imaginary part of the
|
||||
@@ -1252,6 +1287,11 @@ NBJT2ys(TWOdevice *pDevice, SPcomplex *s, SPcomplex *yIeVce, SPcomplex *yIcVce,
|
||||
SPcomplex pIeVce, pIcVce, pIeVbe, pIcVbe;
|
||||
SPcomplex temp, cOmega;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NBJT2ys");
|
||||
}
|
||||
#endif
|
||||
pDevice->solverType = SLV_SMSIG;
|
||||
rhsReal = pDevice->rhs;
|
||||
rhsImag = pDevice->rhsImag;
|
||||
@@ -1375,6 +1415,11 @@ NUMOSys(TWOdevice *pDevice, SPcomplex *s, struct mosAdmittances *yAc)
|
||||
SPcomplex *y;
|
||||
SPcomplex temp, cOmega;
|
||||
|
||||
#ifdef KLU
|
||||
if (pDevice->matrix->CKTkluMODE) {
|
||||
small_signal_check("NUMOSys");
|
||||
}
|
||||
#endif
|
||||
pDevice->solverType = SLV_SMSIG;
|
||||
rhsReal = pDevice->rhs;
|
||||
rhsImag = pDevice->rhsImag;
|
||||
|
||||
@@ -1149,7 +1149,8 @@ TWObindCSC (TWOdevice *pDevice)
|
||||
|
||||
}
|
||||
} else { /* Horizontal Slice */
|
||||
if ( nIndex <= 1 ) { /* Top Side */
|
||||
//if ( nIndex <= 1 ) { /* Top Side */
|
||||
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
|
||||
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
|
||||
|
||||
@@ -786,7 +786,8 @@ TWONbindCSC (TWOdevice *pDevice)
|
||||
|
||||
}
|
||||
} else { /* Horizontal Slice */
|
||||
if ( nIndex <= 1 ) { /* Top Side */
|
||||
//if ( nIndex <= 1 ) { /* Top Side */
|
||||
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
|
||||
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiIn, fNPsiInBinding, nEqn, psiEqnInM) ;
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fNPsiInP1, fNPsiInP1Binding, nEqn, psiEqnInP) ;
|
||||
|
||||
@@ -786,7 +786,8 @@ TWOPbindCSC (TWOdevice *pDevice)
|
||||
|
||||
}
|
||||
} else { /* Horizontal Slice */
|
||||
if ( nIndex <= 1 ) { /* Top Side */
|
||||
//if ( nIndex <= 1 ) { /* Top Side */
|
||||
if ( nIndex == 0 || nIndex == 3 ) { /* Left (Top?) Side : bug 483 */
|
||||
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiIn, fPPsiInBinding, pEqn, psiEqnInM) ;
|
||||
CREATE_KLU_BINDING_TABLE_CIDER(fPPsiInP1, fPPsiInP1Binding, pEqn, psiEqnInP) ;
|
||||
|
||||
@@ -44,7 +44,7 @@ NBJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
ONEmaterial *pM, *pMaterial = NULL, *materialList = NULL;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
#if defined(KLU) && defined(NOT_WITH_CIDER)
|
||||
if (ckt->CKTkluMODE) {
|
||||
fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n");
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
|
||||
@@ -47,7 +47,7 @@ NBJT2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
DOPtable *dopTableList = NULL;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
#if defined(KLU) && defined(NOT_WITH_CIDER)
|
||||
if (ckt->CKTkluMODE) {
|
||||
fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n");
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
|
||||
@@ -46,7 +46,7 @@ NUMDsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
double startTime;
|
||||
|
||||
|
||||
#ifdef KLU
|
||||
#if defined(KLU) && defined(NOT_WITH_CIDER)
|
||||
if (ckt->CKTkluMODE) {
|
||||
fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n");
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
|
||||
@@ -47,7 +47,7 @@ NUMD2setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
DOPtable *dopTableList = NULL;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
#if defined(KLU) && defined(NOT_WITH_CIDER)
|
||||
if (ckt->CKTkluMODE) {
|
||||
fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n");
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
|
||||
@@ -47,7 +47,7 @@ NUMOSsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
|
||||
DOPtable *dopTableList = NULL;
|
||||
double startTime;
|
||||
|
||||
#ifdef KLU
|
||||
#if defined(KLU) && defined(NOT_WITH_CIDER)
|
||||
if (ckt->CKTkluMODE) {
|
||||
fprintf(stderr, "Error: CIDER simulation is not (yet) supported with 'option klu'.\n");
|
||||
fprintf(stderr, " Use 'option sparse' instead.\n");
|
||||
|
||||
Reference in New Issue
Block a user