diff --git a/test-hertz-1.cir b/test-hertz-1.cir index 63d8561e6..e6fc2b44f 100644 --- a/test-hertz-1.cir +++ b/test-hertz-1.cir @@ -1,23 +1,30 @@ +* test ASRC ac analysis with regard to HERTZ and tc1 * (exec-spice "ngspice %s" t) -* holgers save all i, was saved der bei ac ??? id ist reell ? -vin 1 0 dc = 5 ac = 1 +* Test the implementation of the ASRC device with regard to HERTZ and tc1 +* This circuit is deliberatly designed in such a way as to make +* the original incorrect implementation of the ASRC model obvious, +* which incorrectly evaluated the ASRC expression for every frequency +* to recalculate the operating point of the whole circuit +* instead of calculating the operating point from the expression +* when HERTZ=0 +* The diode is deliberatly attached here to expose the difference. +* A second aspect is to check the tc1 parameter of the ASRC + +.temp 27.0 + +v0 1 0 dc = 5 ac = 1 + +b1 1 2 v = 'i(b1) * 1k * (1 + sqrt(hertz/1kHz))' tc1 = 0.01 -*r1 1 2 1k -*br1 1 2 v='i(br1)*1k' -br1 1 2 v = 'i(br1) * 1k * (1 + sqrt(hertz/1kHz))' c2 2 0 30u -d2 2 0 dplain +d2 2 0 dplain temp=27.0 $ keep diode at 27.0 for simplicity -.model dplain d(is=1.0f) - -*uT = kT/e -*i = is * (e^(u/uT - 1) -*di/du = is * e^~ * kT/e = (i + is) / uT +.model dplain d() .control -* default is 1e-12, yet gold is calculated with none +* default is 1e-12, but our golden solution is derived without set gmin = 0 set reltol = 1e-15 @@ -25,55 +32,65 @@ set vntol = 1e-15 *set abstol = 1e-15 *set chgtol = 1e-24 -*! display - let uT = boltz * (273.15 + 27.0) / echarge -* these boltz and echarge are literal from devices/dio +* These 'boltz' and 'echarge' are literal copied from src/spicelib/devices/dio * and differ slightly from our global visible ones let uT = 1.3806226e-23 / 1.6021918e-19 * (273.15 + 27.0) -* echo no arity FIXME !! -*print uT (uT - 0.0258642) - -*! print uT uT-0.0258641863845515 - op -let r = 1k -let is = 1f -let u0 = 5.0 +let u0 = @v0[dc] +let c2 = @c2[capacitance] +let is = @dplain[is] + +let gold_r1_dc = 1k * (1 + ($temp - 27.0) * 0.01) + +* golden solution of the operating point +* uT = kT/e +* i = is * (e^(u/uT - 1) +* di/du = is * e^~ * kT/e = (i + is) / uT let cd = 1m -repeat 5 -let f = cd * r + uT * log(cd/is + 1) - u0 -let f_hat = r + uT / (cd/is + 1) / is -let cd = cd - f/f_hat -let err = cd/-i(vin) - 1 -*print cd+i(vin) -print err +repeat 6 + let f = cd * gold_r1_dc + uT * log(cd/is + 1) - u0 + let f_hat = gold_r1_dc + uT / (cd/is + 1) / is + let cd = cd - f/f_hat + let err = cd/-i(v0) - 1 + echo "iteration: err = $&err" end -*! show all -*! showmod all +let gold_cd = cd +let gold_gd = (cd + is) / uT +let gold_vd = uT * log(cd/is + 1) -let r1_dc = 1k -let d2_gd = @d2[gd] -let c2 = @c2[capacitance] +let err_cd = @d2[id]/gold_cd - 1 +let err_gd = @d2[gd]/gold_gd - 1 +let err_vd = @d2[vd]/gold_vd - 1 -*! print all +* compare golden diode model with ngspice solution +* expect errors of several double floating ULP, roughly 1E-15 + +echo "INFO: err_cd = $&err_cd" +echo "INFO: err_gd = $&err_gd" +echo "INFO: err_vd = $&err_vd" + +* now do the 'ac' analysis ac dec 100 1 1e6 let s = 2*pi*i * frequency -let r1_ac = 1k * (1 + sqrt(frequency/1kHz)) -let H = 1/(1 + r1_ac * (s * op1.c2 + op1.d2_gd)) +let gold_r1_ac = op1.gold_r1_dc * (1 + sqrt(frequency/1kHz)) +let gold_H = 1 / (1 + gold_r1_ac * (s * op1.c2 + op1.gold_gd)) -let err = v(2)/H - 1 -print vecmax(abs(err)) +let err = v(2)/gold_H - 1 +let err_H = vecmax(abs(err)) -plot abs(H) abs(v(2)) +echo "INFO: err_H = $&err_H" + +* expect errors of several double floating ULP, roughly 1E-15 +plot abs(gold_H) abs(v(2)) plot abs(err) .endc diff --git a/test-hertz-1t.cir b/test-hertz-1t.cir deleted file mode 100644 index b350f1530..000000000 --- a/test-hertz-1t.cir +++ /dev/null @@ -1,82 +0,0 @@ -* (exec-spice "ngspice %s" t) - -.temp 37.0 - -* holgers save all i, was saved der bei ac ??? id ist reell ? -vin 1 0 dc = 5 ac = 1 - -*r1 1 2 1k -*br1 1 2 v='i(br1)*1k' -br1 1 2 v = 'i(br1) * 1k * (1 + sqrt(hertz/1kHz))' tc1=0.01 -c2 2 0 30u -* FIXME, the diode doesn't behave as expected when temp != 27.0 -d2 2 0 dplain temp=27.0 - -.model dplain d(is=1.0f) - -*uT = kT/e -*i = is * (e^(u/uT - 1) -*di/du = is * e^~ * kT/e = (i + is) / uT - -.control - -* default is 1e-12, yet gold is calculated with none -set gmin = 0 - -set reltol = 1e-15 -set vntol = 1e-15 -*set abstol = 1e-15 -*set chgtol = 1e-24 - -*! display - -let uT = boltz * (273.15 + 27.0) / echarge - -* these boltz and echarge are literal from devices/dio -* and differ slightly from our global visible ones -let uT = 1.3806226e-23 / 1.6021918e-19 * (273.15 + 27.0) - -* echo no arity FIXME !! -*print uT (uT - 0.0258642) - -*! print uT uT-0.0258641863845515 - -op - -let r = 1k * (1 + 10 * 0.01) -let is = 1f -let u0 = 5.0 - -let cd = 1m -repeat 5 -let f = cd * r + uT * log(cd/is + 1) - u0 -let f_hat = r + uT / (cd/is + 1) / is -let cd = cd - f/f_hat -let err = cd/-i(vin) - 1 -*print cd+i(vin) -print err -end - -*! show all -*! showmod all - -let r1_dc = 1k * (1 + 10 * 0.01) -let d2_gd = @d2[gd] -let c2 = @c2[capacitance] - -*! print all - -ac dec 100 1 1e6 - -let s = 2*pi*i * frequency - -let r1_ac = 1k * (1 + sqrt(frequency/1kHz)) * (1 + 10 * 0.01) -let H = 1/(1 + r1_ac * (s * op1.c2 + op1.d2_gd)) - -let err = v(2)/H - 1 -print vecmax(abs(err)) - -plot abs(H) abs(v(2)) -plot abs(err) - -.endc