diff --git a/src/frontend/com_hb.c b/src/frontend/com_hb.c index a539c3121..f69b8d00f 100644 --- a/src/frontend/com_hb.c +++ b/src/frontend/com_hb.c @@ -59,6 +59,16 @@ com_hb(wordlist *wl) return; } + /* Honor `.option klu`: a bare `hb` builds the circuit here rather than via + * cktdojob (which is where a normal analysis copies task->TSKkluMODE), so pull + * the KLU mode from the task before CKTsetup wires the matrix -- else the matrix + * defaults to Sparse and the `.option klu` request is silently ignored. */ +#ifdef KLU + if (ft_curckt->ci_defTask && + (ckt->CKTmatrix == NULL || SMPmatSize(ckt->CKTmatrix) <= 0)) + ckt->CKTkluMODE = ft_curckt->ci_defTask->TSKkluMODE; +#endif + /* make sure the circuit is built (matrix + states allocated) */ if (ckt->CKTmatrix == NULL || SMPmatSize(ckt->CKTmatrix) <= 0) { if ((err = CKTsetup(ckt)) != OK || (err = CKTtemp(ckt)) != OK) { diff --git a/src/spicelib/analysis/dcpss.c b/src/spicelib/analysis/dcpss.c index 9dfe7eb6e..73a14e5c0 100644 --- a/src/spicelib/analysis/dcpss.c +++ b/src/spicelib/analysis/dcpss.c @@ -1259,7 +1259,21 @@ hb_extract(CKTcircuit *ckt, const double *vsamp, int N, int P, int K, return 1; bsave = TMALLOC(double, N); - spSetComplex(ckt->CKTmatrix->SPmatrix); + /* Matrix must be in complex mode so CKTacLoad stamps G(el[0]) + jC(el[1]) and + * SMPfindElt reads both parts. Under KLU the live matrix is the CSC form, not + * SPmatrix, so bind the device pointers to the complex CSC (mirrors + * pac_extract_harmonics -- this is what makes HB solver-independent). */ +#ifdef KLU + if (ckt->CKTmatrix->CKTkluMODE) { + if (!ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex) { + for (i = 0; i < DEVmaxnum; i++) + if (DEVices[i] && DEVices[i]->DEVbindCSCComplex && ckt->CKThead[i]) + DEVices[i]->DEVbindCSCComplex(ckt->CKThead[i], ckt); + ckt->CKTmatrix->SMPkluMatrix->KLUmatrixIsComplex = KLUMatrixComplex; + } + } else +#endif + spSetComplex(ckt->CKTmatrix->SPmatrix); /* establish structure at sample 0's bias */ for (i = 1; i <= N; i++)