From 5d0786a4490c226faf6ea60e3c862b208b21b1a0 Mon Sep 17 00:00:00 2001 From: couriersud Date: Fri, 17 Jul 2020 23:11:39 +0200 Subject: [PATCH] netlist: prepare road towards trapezoidal integration. * This is a long term transition goal. Documented in source (see NL_USE_BACKWARD_EULER). --- src/lib/netlist/analog/nld_generic_models.h | 8 +++++-- src/lib/netlist/devices/nld_ne555.cpp | 24 ++++++++++++++++---- src/lib/netlist/examples/2N6027.cpp | 5 ---- src/lib/netlist/nl_config.h | 14 ++++++++++++ src/lib/netlist/solver/nld_matrix_solver.cpp | 2 +- 5 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h index ad0e4dad4fd..5ccf386f6fa 100644 --- a/src/lib/netlist/analog/nld_generic_models.h +++ b/src/lib/netlist/analog/nld_generic_models.h @@ -131,7 +131,7 @@ namespace analog nl_fptype m_gmin; }; -#if 1 +#if (NL_USE_BACKWARD_EULER) // Constant model for constant capacitor model // Backward Euler // "Circuit simulation", page 274 @@ -166,7 +166,7 @@ namespace analog struct generic_capacitor_const { public: - generic_capacitor_const(device_t &dev, const pstring &name) + generic_capacitor_const(core_device_t &dev, const pstring &name) : m_gmin(nlconst::zero()) , m_vn(0) , m_in(0) @@ -195,6 +195,10 @@ namespace analog m_trn = h; return { G + m_gmin, -Ieq }; } + void restore_state() noexcept + { + // this one has no state + } void setparams(nl_fptype gmin) noexcept { m_gmin = gmin; } private: nl_fptype m_gmin; diff --git a/src/lib/netlist/devices/nld_ne555.cpp b/src/lib/netlist/devices/nld_ne555.cpp index 3a60b33d328..4e812a0bd53 100644 --- a/src/lib/netlist/devices/nld_ne555.cpp +++ b/src/lib/netlist/devices/nld_ne555.cpp @@ -83,6 +83,7 @@ namespace netlist , m_ff(*this, "m_ff", false) , m_last_reset(*this, "m_last_reset", false) , m_overshoot(*this, "m_overshoot", 0.0) + , m_undershoot(*this, "m_undershoot", 0.0) , m_ovlimit(0.0) { register_subalias("GND", m_R3.N()); // Pin 1 @@ -138,10 +139,13 @@ namespace netlist } else { - const auto delta = m_THRES() + m_overshoot - vthresh; - const bool bthresh = (delta > 0.0); +#if (NL_USE_BACKWARD_EULER) + const bool bthresh = (m_THRES() + m_overshoot > vthresh); const bool btrig = (m_TRIG() - m_overshoot > vtrig); - +#else + const bool bthresh = (m_THRES() + m_overshoot > vthresh); + const bool btrig = (m_TRIG() - m_undershoot > vtrig); +#endif if (!btrig) m_ff = true; else if (bthresh) @@ -154,7 +158,11 @@ namespace netlist if (m_last_out && !out) { - m_overshoot += ((m_THRES() - vthresh)) * 2; +#if (NL_USE_BACKWARD_EULER) + m_overshoot += ((m_THRES() - vthresh)) * 2.0; +#else + m_overshoot += ((m_THRES() - vthresh)); +#endif m_overshoot = plib::clamp(m_overshoot(), nlconst::zero(), ovlimit); //if (this->name() == "IC6_2") // printf("%f %s %f %f %f\n", exec().time().as_double(), this->name().c_str(), m_overshoot(), m_R2.P()(), m_THRES()); @@ -166,8 +174,13 @@ namespace netlist } else if (!m_last_out && out) { - m_overshoot += (vtrig - m_TRIG()) * 2; +#if (NL_USE_BACKWARD_EULER) + m_overshoot += (vtrig - m_TRIG()) * 2.0; m_overshoot = plib::clamp(m_overshoot(), nlconst::zero(), ovlimit); +#else + m_undershoot += (vtrig - m_TRIG()); + m_undershoot = plib::clamp(m_undershoot(), nlconst::zero(), ovlimit); +#endif m_RDIS.change_state([this]() { m_RDIS.set_R(nlconst::magic(R_OFF)); @@ -193,6 +206,7 @@ namespace netlist state_var m_ff; state_var m_last_reset; state_var m_overshoot; + state_var m_undershoot; nl_fptype m_ovlimit; nl_fptype clamp_hl(const nl_fptype v, const nl_fptype a, const nl_fptype b) noexcept diff --git a/src/lib/netlist/examples/2N6027.cpp b/src/lib/netlist/examples/2N6027.cpp index 777369929b1..bfad3c065ec 100644 --- a/src/lib/netlist/examples/2N6027.cpp +++ b/src/lib/netlist/examples/2N6027.cpp @@ -28,14 +28,9 @@ NETLIST_EXTERNAL(loc_lib) NETLIST_START(ex2N6027) - /* This is a circuit pushing the solvers to the limits - * 50,000 maximum NR loops. - */ SOLVER(Solver, 48000) - PARAM(Solver.ACCURACY, 1e-5) PARAM(Solver.DYNAMIC_TS, 1) PARAM(Solver.DYNAMIC_MIN_TIMESTEP, 1e-9) - PARAM(Solver.NR_LOOPS, 50000) PARAM(Solver.METHOD, "MAT_CR") LOCAL_SOURCE(loc_lib) diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index 5fa33a27295..ed8953ba842 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -97,6 +97,20 @@ #define NL_USE_COPY_INSTEAD_OF_REFERENCE (0) #endif +/// \brief Use backward Euler integration +/// +/// This will use backward Euler instead of trapezoidal integration. +/// +/// FIXME: Longterm this will become a runtime setting. Only the capacitor model +/// currently has a trapezoidal version and there is no support currently for +/// variable capacitors. +/// The change will have impact on timings since trapezoidal improves timing +/// accuracy. + +#ifndef NL_USE_BACKWARD_EULER +#define NL_USE_BACKWARD_EULER (1) +#endif + /// \brief Use the truthtable implementation of 7448 instead of the coded device /// /// FIXME: Using truthtable is a lot slower than the explicit device diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 2e0b50dcf64..8c46699416b 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -532,7 +532,7 @@ namespace solver if (dynamic_device_count() != 0) { step(timestep_type::FORWARD, delta); - auto resched = solve_nr_base(); + const auto resched = solve_nr_base(); if (resched) return newton_loops_exceeded(delta);