From 0638aaa1604c3f94221f0a3e489f956ed870043a Mon Sep 17 00:00:00 2001 From: Keith OHara Date: Mon, 6 Apr 2026 00:01:12 +0200 Subject: [PATCH 1/3] Continue Newton iteration until currents settle. For each type of device, a *convTest function determines if the current through that device is converged within tolerance, and sets CKTnoncon if the current is not yet converged. ASCRconvTest() erroneously subtracted old current from old, rather than old from new, when evaluating convergence. Also, since at least 3f5, the calling function NIconvTest assumed that the worker functions indicated non-convergence through their return value, so was ignoring the reports of current nonconvergence. --- src/maths/ni/niconv.c | 9 +++++++++ src/spicelib/devices/asrc/asrcconv.c | 2 +- tests/regression/misc/Makefile.am | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/maths/ni/niconv.c b/src/maths/ni/niconv.c index 5d24a23bf..355fa5bd8 100644 --- a/src/maths/ni/niconv.c +++ b/src/maths/ni/niconv.c @@ -81,6 +81,15 @@ NIconvTest(CKTcircuit *ckt) #ifdef NEWCONV i = CKTconvTest(ckt); + /* The individual testers, called by CKTconvTest, set + * ckt->CKTnoncon and ckt->CKTtroubleElt appropriately. */ + if (ckt->CKTnoncon != 0) { + ckt->CKTtroubleNode = 0; + return(1); + } + /* CKTconvTest early-returns nonzero 'i' on the first error + * in evaluating convergence (such as parameter out of range) so + * there may be untested devices that have not yet converged */ if (i) ckt->CKTtroubleNode = 0; return(i); diff --git a/src/spicelib/devices/asrc/asrcconv.c b/src/spicelib/devices/asrc/asrcconv.c index 4fa584a74..459838797 100644 --- a/src/spicelib/devices/asrc/asrcconv.c +++ b/src/spicelib/devices/asrc/asrcconv.c @@ -32,7 +32,7 @@ ASRCconvTest(GENmodel *inModel, CKTcircuit *ckt) } for (i = 0; i < here->ASRCtree->numVars; i++) - asrc_vals[i] = ckt->CKTrhsOld[here->ASRCvars[i]]; + asrc_vals[i] = ckt->CKTrhs[here->ASRCvars[i]]; if (here->ASRCtree->IFeval(here->ASRCtree, ckt->CKTgmin, &rhs, asrc_vals, asrc_derivs) != OK) diff --git a/tests/regression/misc/Makefile.am b/tests/regression/misc/Makefile.am index 5c9ac9d80..d485a8f10 100644 --- a/tests/regression/misc/Makefile.am +++ b/tests/regression/misc/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to produce Makefile.in -TESTS = bugs-1.cir bugs-2.cir dollar-1.cir empty-1.cir resume-1.cir log-functions-1.cir alter-vec.cir test-noise-2.cir test-noise-3.cir ac-zero.cir asrc-tc-1.cir asrc-tc-2.cir if-elseif.cir +TESTS = bugs-1.cir bugs-2.cir dollar-1.cir empty-1.cir resume-1.cir log-functions-1.cir alter-vec.cir test-noise-2.cir test-noise-3.cir ac-zero.cir asrc-tc-1.cir asrc-tc-2.cir if-elseif.cir convergence.cir TESTS_ENVIRONMENT = ngspice_vpath=$(srcdir) $(SHELL) $(top_srcdir)/tests/bin/check.sh $(top_builddir)/src/ngspice From 8abfb5aeb05383f693088c56d746a84ceaa16dc7 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Mon, 6 Apr 2026 14:15:42 +0200 Subject: [PATCH 2/3] Remove unused ft_gidb Add debug ft_shvecsearch Make ft_codemodelerror more verbose. --- src/frontend/com_dl.c | 2 +- src/frontend/inpcom.c | 3 ++- src/frontend/miscvars.c | 2 +- src/frontend/options.c | 8 ++++---- src/include/ngspice/fteext.h | 4 ++-- src/sharedspice.c | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/frontend/com_dl.c b/src/frontend/com_dl.c index 6cc5202e9..682b7c4d8 100644 --- a/src/frontend/com_dl.c +++ b/src/frontend/com_dl.c @@ -15,7 +15,7 @@ if (wl && wl->wl_word) if (load_opus(wl->wl_word)) { fprintf(stderr, "Error: Library %s couldn't be loaded!\n", wl->wl_word); ft_spiniterror = TRUE; - ft_codemodelerror = TRUE; + ft_codemodelerror = copy(wl->wl_word); if (ft_stricterror) /* if set in spinit */ controlled_exit(EXIT_BAD); } diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 26e37d7ec..b09c201cd 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -1111,8 +1111,9 @@ struct card *inp_readall(FILE *fp, const char *dir_name, const char* file_name, fprintf(stderr, " Any of the following steps may fail, if Verilog A models are involved!.\n\n"); } if (ft_codemodelerror) { - fprintf(stderr, "Warning: code models like analog.cm have not been loaded successfully.\n"); + fprintf(stderr, "Warning: code models like %s have not been loaded successfully.\n", ft_codemodelerror); fprintf(stderr, " Any of the following steps may fail, if code models are involved!.\n\n"); + tfree(ft_codemodelerror); } struct nscope *root = inp_add_levels(working); diff --git a/src/frontend/miscvars.c b/src/frontend/miscvars.c index c157a9666..3accd43f4 100644 --- a/src/frontend/miscvars.c +++ b/src/frontend/miscvars.c @@ -18,9 +18,9 @@ bool ft_vecdb = FALSE; bool ft_simdb = FALSE; bool ft_evdb = FALSE; bool ft_grdb = FALSE; -bool ft_gidb = FALSE; bool ft_controldb = FALSE; bool ft_asyncdb = FALSE; +bool ft_shvecsearch = FALSE; char *ft_setkwords[] = { diff --git a/src/frontend/options.c b/src/frontend/options.c index 24f113001..38041cd32 100644 --- a/src/frontend/options.c +++ b/src/frontend/options.c @@ -25,7 +25,7 @@ bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE; bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE; bool ft_norefprint = FALSE; bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE, ft_spiniterror = FALSE; -bool ft_codemodelerror = FALSE, ft_osdierror = FALSE; +char *ft_codemodelerror = NULL, ft_osdierror = FALSE; static void setdb(char *str); static struct variable *cp_enqvec_as_var(const char *vec_name, @@ -283,7 +283,7 @@ cp_usrset(struct variable *var, bool isset) if (eq(var->va_name, "debug")) { if (var->va_type == CP_BOOL) { cp_debug = ft_simdb = ft_parsedb = ft_evdb = ft_vecdb = - ft_grdb = ft_gidb = ft_controldb = isset; + ft_grdb = ft_controldb = isset; } else if (var->va_type == CP_LIST) { for (tv = var->va_vlist; tv; tv = tv->va_next) if (var->va_type == CP_STRING) @@ -477,12 +477,12 @@ setdb(char *str) ft_vecdb = TRUE; else if (eq(str, "graf")) ft_grdb = TRUE; - else if (eq(str, "ginterface")) - ft_gidb = TRUE; else if (eq(str, "control")) ft_controldb = TRUE; else if (eq(str, "async")) ft_asyncdb = TRUE; + else if (eq(str, "shvecsearch")) + ft_shvecsearch = TRUE; else fprintf(cp_err, "Warning: no such debug class %s\n", str); } diff --git a/src/include/ngspice/fteext.h b/src/include/ngspice/fteext.h index e161938a1..cbec2250f 100644 --- a/src/include/ngspice/fteext.h +++ b/src/include/ngspice/fteext.h @@ -238,7 +238,6 @@ extern bool ft_parsedb; extern bool ft_evdb; extern bool ft_vecdb; extern bool ft_grdb; -extern bool ft_gidb; extern bool ft_controldb; extern bool ft_asyncdb; extern char *ft_setkwords[]; @@ -248,8 +247,9 @@ extern bool ft_ngdebug; extern bool ft_nginfo; extern bool ft_stricterror; extern bool ft_spiniterror; -extern bool ft_codemodelerror; +extern char *ft_codemodelerror; extern bool ft_osdierror; +extern bool ft_shvecsearch; /* parse.c */ diff --git a/src/sharedspice.c b/src/sharedspice.c index b7c660c87..acc814887 100644 --- a/src/sharedspice.c +++ b/src/sharedspice.c @@ -1181,7 +1181,7 @@ pvector_info ngGet_Vec_Info(char* vecname) { struct dvec* newvec; - if (ft_ngdebug) + if (ft_shvecsearch) fprintf(stdout, "\nGet vector info: searching for vector '%s'\n", vecname); if (!is_initialized) { From afd4eb64ed38f8085a506f29f7d03d117623b1e4 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Tue, 7 Apr 2026 22:25:27 +0200 Subject: [PATCH 3/3] Fix a bug introduced by yesterday's commit https://sourceforge.net/p/ngspice/ngspice/ci/8abfb5aeb05383f693088c56d746a84ceaa16dc7/ --- src/frontend/options.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frontend/options.c b/src/frontend/options.c index 38041cd32..0eeb41b0a 100644 --- a/src/frontend/options.c +++ b/src/frontend/options.c @@ -25,7 +25,8 @@ bool ft_acctprint = FALSE, ft_noacctprint = FALSE, ft_listprint = FALSE; bool ft_nodesprint = FALSE, ft_optsprint = FALSE, ft_noinitprint = FALSE; bool ft_norefprint = FALSE; bool ft_ngdebug = FALSE, ft_nginfo = FALSE, ft_stricterror = FALSE, ft_spiniterror = FALSE; -char *ft_codemodelerror = NULL, ft_osdierror = FALSE; +bool ft_osdierror = FALSE; +char* ft_codemodelerror = NULL; static void setdb(char *str); static struct variable *cp_enqvec_as_var(const char *vec_name,