netlist: add RELTOL/VNTOL solver parameters. Type safety. [Couriersud]

The newly added RELTOL and VNTOL parameters implement Newton convergence
checks comparable following other SPICE implementations.
The ACCURACY solver parameter now is only used for convergence checks in
iterative solvers.

In addition, type safety was significantly improved and a lot of "magic"
numbers are identifiable now.
This commit is contained in:
couriersud 2019-11-02 22:25:11 +01:00
parent 7518cc226b
commit 77ea61bac7
44 changed files with 510 additions and 437 deletions

View File

@ -21,17 +21,22 @@ namespace analog
class diode
{
public:
diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(plib::reciprocal(m_VT)) {}
diode()
: m_Is(plib::constants<nl_fptype>::cast(1e-15))
, m_VT(plib::constants<nl_fptype>::cast(0.0258))
, m_VT_inv(plib::reciprocal(m_VT))
{}
diode(const nl_fptype Is, const nl_fptype n)
{
m_Is = Is;
m_VT = 0.0258 * n;
m_VT = plib::constants<nl_fptype>::cast(0.0258) * n;
m_VT_inv = plib::reciprocal(m_VT);
}
void set(const nl_fptype Is, const nl_fptype n)
{
m_Is = Is;
m_VT = 0.0258 * n;
m_VT = plib::constants<nl_fptype>::cast(0.0258) * n;
m_VT_inv = plib::reciprocal(m_VT);
}
nl_fptype I(const nl_fptype V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
@ -179,9 +184,9 @@ namespace analog
, m_RB(*this, "m_RB", true)
, m_RC(*this, "m_RC", true)
, m_BC(*this, "m_BC", true)
, m_gB(1e-9)
, m_gC(1e-9)
, m_V(0.0)
, m_gB(plib::constants<nl_fptype>::cast(1e-9))
, m_gC(plib::constants<nl_fptype>::cast(1e-9))
, m_V(plib::constants<nl_fptype>::zero())
, m_state_on(*this, "m_state_on", 0)
{
register_subalias("B", m_RB.m_P);
@ -237,13 +242,13 @@ namespace analog
connect(m_D_EB.m_N, m_D_CB.m_N);
connect(m_D_CB.m_P, m_D_EC.m_N);
if (m_model.m_CJE > 0.0)
if (m_model.m_CJE > plib::constants<nl_fptype>::zero())
{
create_and_register_subdevice("m_CJE", m_CJE);
connect("B", "m_CJE.1");
connect("E", "m_CJE.2");
}
if (m_model.m_CJC > 0.0)
if (m_model.m_CJC > plib::constants<nl_fptype>::zero())
{
create_and_register_subdevice("m_CJC", m_CJC);
connect("B", "m_CJC.1");
@ -292,13 +297,14 @@ namespace analog
NETLIB_RESET(QBJT_switch)
{
NETLIB_NAME(QBJT)::reset();
const auto zero(plib::constants<nl_fptype>::zero());
m_state_on = 0;
m_RB.set_G_V_I(exec().gmin(), 0.0, 0.0);
m_RC.set_G_V_I(exec().gmin(), 0.0, 0.0);
m_RB.set_G_V_I(exec().gmin(), zero, zero);
m_RC.set_G_V_I(exec().gmin(), zero, zero);
m_BC.set_G_V_I(exec().gmin() / 10.0, 0.0, 0.0);
m_BC.set_G_V_I(exec().gmin() / plib::constants<nl_fptype>::cast(10.0), zero, zero);
}
@ -323,24 +329,25 @@ namespace analog
set_qtype((m_model.type() == "NPN") ? BJT_NPN : BJT_PNP);
nl_fptype alpha = BF / (1.0 + BF);
nl_fptype alpha = BF / (plib::constants<nl_fptype>::one() + BF);
diode d(IS, NF);
// Assume 5mA Collector current for switch operation
m_V = d.V(0.005 / alpha);
const auto cc(plib::constants<nl_fptype>::cast(0.005));
m_V = d.V(cc / alpha);
/* Base current is 0.005 / beta
* as a rough estimate, we just scale the conductance down */
m_gB = plib::reciprocal((m_V/(0.005 / BF)));
m_gB = plib::reciprocal((m_V/(cc / BF)));
//m_gB = d.gI(0.005 / alpha);
if (m_gB < exec().gmin())
m_gB = exec().gmin();
m_gC = d.gI(0.005); // very rough estimate
m_gC = d.gI(cc); // very rough estimate
}
NETLIB_UPDATE_TERMINALS(QBJT_switch)
@ -350,12 +357,13 @@ namespace analog
const unsigned new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
if (m_state_on ^ new_state)
{
const auto zero(plib::constants<nl_fptype>::zero());
const nl_fptype gb = new_state ? m_gB : exec().gmin();
const nl_fptype gc = new_state ? m_gC : exec().gmin();
const nl_fptype v = new_state ? m_V * m : 0;
const nl_fptype v = new_state ? m_V * m : zero;
m_RB.set_G_V_I(gb, v, 0.0);
m_RC.set_G_V_I(gc, 0.0, 0.0);
m_RB.set_G_V_I(gb, v, zero);
m_RC.set_G_V_I(gc, zero, zero);
m_state_on = new_state;
}
}
@ -395,7 +403,7 @@ namespace analog
NETLIB_UPDATE_TERMINALS(QBJT_EB)
{
const nl_fptype polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
const nl_fptype polarity = plib::constants<nl_fptype>::cast(qtype() == BJT_NPN ? 1.0 : -1.0);
m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
@ -431,8 +439,8 @@ namespace analog
set_qtype((m_model.type() == "NPN") ? BJT_NPN : BJT_PNP);
m_alpha_f = BF / (1.0 + BF);
m_alpha_r = BR / (1.0 + BR);
m_alpha_f = BF / (plib::constants<nl_fptype>::one() + BF);
m_alpha_r = BR / (plib::constants<nl_fptype>::one() + BR);
m_gD_BE.set_param(IS / m_alpha_f, NF, exec().gmin(), constants::T0());
m_gD_BC.set_param(IS / m_alpha_r, NR, exec().gmin(), constants::T0());

View File

@ -38,10 +38,10 @@ namespace analog
{
public:
generic_capacitor(device_t &dev, const pstring &name)
: m_h(dev, name + ".m_h", 0.0)
, m_c(dev, name + ".m_c", 0.0)
, m_v(dev, name + ".m_v", 0.0)
, m_gmin(0.0)
: m_h(dev, name + ".m_h", plib::constants<nl_fptype>::zero())
, m_c(dev, name + ".m_c", plib::constants<nl_fptype>::zero())
, m_v(dev, name + ".m_v", plib::constants<nl_fptype>::zero())
, m_gmin(plib::constants<nl_fptype>::zero())
{
}
@ -57,7 +57,7 @@ namespace analog
nl_fptype G(nl_fptype cap) const
{
//return m_h * cap + m_gmin;
return m_h * 0.5 * (cap + m_c) + m_gmin;
return m_h * plib::constants<nl_fptype>::half() * (cap + m_c) + m_gmin;
//return m_h * cap + m_gmin;
}
@ -65,7 +65,7 @@ namespace analog
{
plib::unused_var(v);
//return -m_h * 0.5 * ((cap + m_c) * m_v + (cap - m_c) * v) ;
return -m_h * 0.5 * (cap + m_c) * m_v;
return -m_h * plib::constants<nl_fptype>::half() * (cap + m_c) * m_v;
//return -m_h * cap * m_v;
}
@ -91,9 +91,9 @@ namespace analog
{
public:
generic_capacitor(device_t &dev, const pstring &name)
: m_h(dev, name + ".m_h", 0.0)
, m_v(dev, name + ".m_v", 0.0)
, m_gmin(0.0)
: m_h(dev, name + ".m_h", plib::constants<nl_fptype>::zero())
, m_v(dev, name + ".m_v", plib::constants<nl_fptype>::zero())
, m_gmin(plib::constants<nl_fptype>::zero())
{
}
@ -133,25 +133,29 @@ namespace analog
{
public:
generic_diode(device_t &dev, const pstring &name)
: m_Vd(dev, name + ".m_Vd", 0.7)
, m_Id(dev, name + ".m_Id", 0.0)
, m_G(dev, name + ".m_G", 1e-15)
, m_Vt(0.0)
, m_Vmin(0.0) // not used in MOS model
, m_Is(0.0)
, m_logIs(0.0)
, m_n(0.0)
, m_gmin(1e-15)
, m_VtInv(0.0)
, m_Vcrit(0.0)
: m_Vd(dev, name + ".m_Vd", plib::constants<nl_fptype>::cast(0.7))
, m_Id(dev, name + ".m_Id", plib::constants<nl_fptype>::zero())
, m_G(dev, name + ".m_G", plib::constants<nl_fptype>::cast(1e-15))
, m_Vt(plib::constants<nl_fptype>::zero())
, m_Vmin(plib::constants<nl_fptype>::zero()) // not used in MOS model
, m_Is(plib::constants<nl_fptype>::zero())
, m_logIs(plib::constants<nl_fptype>::zero())
, m_n(plib::constants<nl_fptype>::zero())
, m_gmin(plib::constants<nl_fptype>::cast(1e-15))
, m_VtInv(plib::constants<nl_fptype>::zero())
, m_Vcrit(plib::constants<nl_fptype>::zero())
, m_name(name)
{
set_param(1e-15, 1, 1e-15, 300.0);
set_param(
plib::constants<nl_fptype>::cast(1e-15)
, plib::constants<nl_fptype>::cast(1)
, plib::constants<nl_fptype>::cast(1e-15)
, plib::constants<nl_fptype>::cast(300.0));
}
void update_diode(const nl_fptype nVd)
{
nl_fptype IseVDVt(0.0);
nl_fptype IseVDVt(plib::constants<nl_fptype>::zero());
if (TYPE == diode_e::BIPOLAR)
{
@ -160,7 +164,7 @@ namespace analog
{
const nl_fptype d = std::min(+fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd - m_Vd);
const nl_fptype a = std::abs(d) * m_VtInv;
m_Vd = m_Vd + (d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt;
m_Vd = m_Vd + plib::constants<nl_fptype>::cast(d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt;
}
else
m_Vd = std::max(-fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd);
@ -205,7 +209,7 @@ namespace analog
m_Vt = m_n * temp * constants::k_b() / constants::Q_e();
m_Vmin = -5.0 * m_Vt;
m_Vmin = plib::constants<nl_fptype>::cast(-5.0) * m_Vt;
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / constants::sqrt2());
m_VtInv = constants::one() / m_Vt;

View File

@ -195,20 +195,20 @@ namespace analog
, m_cap_gb(*this, "m_cap_gb")
, m_cap_gs(*this, "m_cap_gs")
, m_cap_gd(*this, "m_cap_gd")
, m_phi(0.0)
, m_gamma(0.0)
, m_vto(0.0)
, m_beta(0.0)
, m_lambda(0.0)
, m_Leff(0.0)
, m_CoxWL(0.0)
, m_polarity(qtype() == FET_NMOS ? 1.0 : -1.0)
, m_Cgb(0.0)
, m_Cgs(0.0)
, m_Cgd(0.0)
, m_phi(plib::constants<nl_fptype>::zero())
, m_gamma(plib::constants<nl_fptype>::zero())
, m_vto(plib::constants<nl_fptype>::zero())
, m_beta(plib::constants<nl_fptype>::zero())
, m_lambda(plib::constants<nl_fptype>::zero())
, m_Leff(plib::constants<nl_fptype>::zero())
, m_CoxWL(plib::constants<nl_fptype>::zero())
, m_polarity(plib::constants<nl_fptype>::cast(qtype() == FET_NMOS ? 1.0 : -1.0))
, m_Cgb(plib::constants<nl_fptype>::zero())
, m_Cgs(plib::constants<nl_fptype>::zero())
, m_Cgd(plib::constants<nl_fptype>::zero())
, m_capmod(2)
, m_Vgs(*this, "m_Vgs", 0.0)
, m_Vgd(*this, "m_Vgd", 0.0)
, m_Vgs(*this, "m_Vgs", plib::constants<nl_fptype>::zero())
, m_Vgd(*this, "m_Vgd", plib::constants<nl_fptype>::zero())
{
register_subalias("S", m_SG.m_P); // Source
register_subalias("G", m_SG.m_N); // Gate
@ -220,7 +220,7 @@ namespace analog
connect(m_DG.m_P, m_SD.m_N);
set_qtype((m_model.type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS);
m_polarity = qtype() == FET_NMOS ? 1.0 : -1.0;
m_polarity = qtype() == plib::constants<nl_fptype>::cast(FET_NMOS ? 1.0 : -1.0);
m_capmod = m_model.m_CAPMOD;
// printf("capmod %d %g %g\n", m_capmod, (nl_fptype)m_model.m_VTO, m_polarity);
@ -241,46 +241,49 @@ namespace analog
// calculate effective channel length
m_Leff = m_model.m_L - 2 * m_model.m_LD;
nl_assert_always(m_Leff > 0.0, "Effective Lateral diffusion would be negative for model " + m_model.name());
nl_assert_always(m_Leff > plib::constants<nl_fptype>::zero(), "Effective Lateral diffusion would be negative for model " + m_model.name());
nl_fptype Cox = (m_model.m_TOX > 0.0) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : 0.0;
nl_fptype Cox = (m_model.m_TOX > plib::constants<nl_fptype>::zero()) ? (constants::eps_SiO2() * constants::eps_0() / m_model.m_TOX) : plib::constants<nl_fptype>::zero();
// calculate DC transconductance coefficient
if (m_model.m_KP > 0)
if (m_model.m_KP > plib::constants<nl_fptype>::zero())
m_beta = m_model.m_KP * m_model.m_W / m_Leff;
else if (Cox > 0 && m_model.m_UO > 0)
m_beta = m_model.m_UO * 1e-4 * Cox * m_model.m_W / m_Leff;
else if (Cox > plib::constants<nl_fptype>::zero() && m_model.m_UO > plib::constants<nl_fptype>::zero())
m_beta = m_model.m_UO * plib::constants<nl_fptype>::cast(1e-4) * Cox * m_model.m_W / m_Leff;
else
m_beta = 2e-5 * m_model.m_W / m_Leff;
m_beta = plib::constants<nl_fptype>::cast(2e-5) * m_model.m_W / m_Leff;
//FIXME::UT can disappear
const nl_fptype Vt = constants::T0() * constants::k_b() / constants::Q_e();
// calculate surface potential if not given
if (m_model.m_PHI > 0.0)
if (m_model.m_PHI > plib::constants<nl_fptype>::zero())
m_phi = m_model.m_PHI;
else if (m_model.m_NSUB > 0.0)
else if (m_model.m_NSUB > plib::constants<nl_fptype>::zero())
{
nl_assert_always(m_model.m_NSUB * 1e6 >= constants::NiSi(), "Error calculating phi for model " + m_model.name());
m_phi = 2 * Vt * std::log (m_model.m_NSUB * 1e6 / constants::NiSi());
nl_assert_always(m_model.m_NSUB * plib::constants<nl_fptype>::cast(1e6) >= constants::NiSi(), "Error calculating phi for model " + m_model.name());
m_phi = plib::constants<nl_fptype>::two() * Vt * std::log (m_model.m_NSUB * plib::constants<nl_fptype>::cast(1e6) / constants::NiSi());
}
else
m_phi = 0.6;
m_phi = plib::constants<nl_fptype>::cast(0.6);
// calculate bulk threshold if not given
if (m_model.m_GAMMA > 0.0)
if (m_model.m_GAMMA > plib::constants<nl_fptype>::zero())
m_gamma = m_model.m_GAMMA;
else
{
if (Cox > 0.0 && m_model.m_NSUB > 0)
m_gamma = std::sqrt (2.0 * constants::Q_e() * constants::eps_Si() * constants::eps_0() * m_model.m_NSUB * 1e6) / Cox;
if (Cox > plib::constants<nl_fptype>::zero() && m_model.m_NSUB > plib::constants<nl_fptype>::zero())
m_gamma = std::sqrt (plib::constants<nl_fptype>::two()
* constants::Q_e() * constants::eps_Si() * constants::eps_0()
* m_model.m_NSUB * plib::constants<nl_fptype>::cast(1e6)) / Cox;
else
m_gamma = 0.0;
m_gamma = plib::constants<nl_fptype>::zero();
}
m_vto = m_model.m_VTO;
if(m_vto != 0.0)
// FIXME zero conversion
if(m_vto != plib::constants<nl_fptype>::zero())
log().warning(MW_MOSFET_THRESHOLD_VOLTAGE(m_model.name()));
/* FIXME: VTO if missing may be calculated from TPG, NSS and temperature. Usually models
@ -302,7 +305,7 @@ namespace analog
//const nl_nl_fptype Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
const nl_fptype Ugd = m_Vgd; // Gate - Drain
const nl_fptype Ugs = m_Vgs; // Gate - Source
const nl_fptype Ubs = 0.0; // Bulk - Source == 0 if connected
const nl_fptype Ubs = plib::constants<nl_fptype>::zero(); // Bulk - Source == 0 if connected
const nl_fptype Ugb = Ugs - Ubs;
m_cap_gb.timestep(m_Cgb, Ugb, step);
@ -385,21 +388,21 @@ namespace analog
if (Vctrl <= -m_phi)
{
Cgb = m_CoxWL;
Cgs = 0.0;
Cgd = 0.0;
Cgs = plib::constants<nl_fptype>::zero();
Cgd = plib::constants<nl_fptype>::zero();
}
else if (Vctrl <= -m_phi / 2.0)
else if (Vctrl <= -m_phi / plib::constants<nl_fptype>::two())
{
Cgb = -Vctrl * m_CoxWL / m_phi;
Cgs = 0.0;
Cgd = 0.0;
Cgs = plib::constants<nl_fptype>::zero();
Cgd = plib::constants<nl_fptype>::zero();
}
// Depletion
else if (Vctrl <= 0)
{
Cgb = -Vctrl * m_CoxWL / m_phi;
Cgs = Vctrl * m_CoxWL * (4.0 / 3.0) / m_phi + (2.0 / 3.0) * m_CoxWL;
Cgd = 0.0;
Cgs = Vctrl * m_CoxWL * plib::constants<nl_fptype>::cast(4.0 / 3.0) / m_phi + plib::constants<nl_fptype>::cast(2.0 / 3.0) * m_CoxWL;
Cgd = plib::constants<nl_fptype>::zero();
}
else
{
@ -408,18 +411,18 @@ namespace analog
// saturation
if (Vdsat <= Vds)
{
Cgb = 0;
Cgs = (2.0 / 3.0) * m_CoxWL;
Cgd = 0;
Cgb = plib::constants<nl_fptype>::zero();
Cgs = plib::constants<nl_fptype>::cast(2.0 / 3.0) * m_CoxWL;
Cgd = plib::constants<nl_fptype>::zero();
}
else
{
// linear
const nl_fptype Sqr1 = std::pow(Vdsat - Vds, 2);
const nl_fptype Sqr2 = std::pow(2.0 * Vdsat - Vds, 2);
const nl_fptype Sqr1 = static_cast<nl_fptype>(std::pow(Vdsat - Vds, 2));
const nl_fptype Sqr2 = static_cast<nl_fptype>(std::pow(plib::constants<nl_fptype>::two() * Vdsat - Vds, 2));
Cgb = 0;
Cgs = m_CoxWL * (1.0 - Sqr1 / Sqr2) * (2.0 / 3.0);
Cgd = m_CoxWL * (1.0 - Vdsat * Vdsat / Sqr2) * (2.0 / 3.0);
Cgs = m_CoxWL * (plib::constants<nl_fptype>::one() - Sqr1 / Sqr2) * plib::constants<nl_fptype>::cast(2.0 / 3.0);
Cgd = m_CoxWL * (plib::constants<nl_fptype>::one() - Vdsat * Vdsat / Sqr2) * plib::constants<nl_fptype>::cast(2.0 / 3.0);
}
}
}
@ -447,16 +450,16 @@ namespace analog
// limit step sizes
const nl_fptype k = 3.5; // see "Circuit Simulation", page 185
const nl_fptype k = plib::constants<nl_fptype>::cast(3.5); // see "Circuit Simulation", page 185
nl_fptype d = (Vgs - m_Vgs);
Vgs = m_Vgs + plib::reciprocal(k) * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
Vgs = m_Vgs + plib::reciprocal(k) * plib::constants<nl_fptype>::cast(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
d = (Vgd - m_Vgd);
Vgd = m_Vgd + plib::reciprocal(k) * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
Vgd = m_Vgd + plib::reciprocal(k) * plib::constants<nl_fptype>::cast(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
m_Vgs = Vgs;
m_Vgd = Vgd;
const nl_fptype Vbs = 0.0; // Bulk - Source == 0 if connected
const nl_fptype Vbs = plib::constants<nl_fptype>::zero(); // Bulk - Source == 0 if connected
//const nl_nl_fptype Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain
const nl_fptype Vds = Vgs - Vgd;
const nl_fptype Vbd = -Vds; // Bulk - Drain = Source - Drain
@ -468,11 +471,11 @@ namespace analog
// Are we in forward mode ?
// in backward mode, just swap source and drain
const bool is_forward = Vds >= 0;
const bool is_forward = Vds >= plib::constants<nl_fptype>::zero();
// calculate Vth
const nl_fptype Vbulk = is_forward ? Vbs : Vbd;
const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : 0.0;
const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : plib::constants<nl_fptype>::zero();
const nl_fptype Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi));
const nl_fptype Vctrl = (is_forward ? Vgs : Vgd) - Vth;
@ -480,34 +483,34 @@ namespace analog
nl_fptype Ids(0), gm(0), gds(0), gmb(0);
const nl_fptype absVds = std::abs(Vds);
if (Vctrl <= 0.0)
if (Vctrl <= plib::constants<nl_fptype>::zero())
{
// cutoff region
Ids = 0.0;
gm = 0.0;
gds = 0.0;
gmb = 0.0;
Ids = plib::constants<nl_fptype>::zero();
gm = plib::constants<nl_fptype>::zero();
gds = plib::constants<nl_fptype>::zero();
gmb = plib::constants<nl_fptype>::zero();
}
else
{
const nl_fptype beta = m_beta * (1.0 + m_lambda * absVds);
const nl_fptype beta = m_beta * (plib::constants<nl_fptype>::one() + m_lambda * absVds);
if (Vctrl <= absVds)
{
// saturation region
Ids = beta * Vctrl * Vctrl / 2.0;
Ids = beta * Vctrl * Vctrl / plib::constants<nl_fptype>::two();
gm = beta * Vctrl;
gds = m_lambda * m_beta * Vctrl * Vctrl / 2.0;
gds = m_lambda * m_beta * Vctrl * Vctrl / plib::constants<nl_fptype>::two();
}
else
{
// linear region
Ids = beta * absVds * (Vctrl - absVds / 2);
Ids = beta * absVds * (Vctrl - absVds / plib::constants<nl_fptype>::two());
gm = beta * absVds;
gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / 2.0);
gds = beta * (Vctrl - absVds) + m_lambda * m_beta * absVds * (Vctrl - absVds / plib::constants<nl_fptype>::two());
}
// backgate transconductance
const nl_fptype bgtc = (phi_m_Vbulk != 0.0) ? (m_gamma / phi_m_Vbulk / 2.0) : 0.0;
const nl_fptype bgtc = (phi_m_Vbulk != plib::constants<nl_fptype>::zero()) ? (m_gamma / phi_m_Vbulk / plib::constants<nl_fptype>::two()) : plib::constants<nl_fptype>::zero();
gmb = gm * bgtc;
}
@ -524,27 +527,27 @@ namespace analog
const nl_fptype IeqBS = m_D_BS.Ieq();
const nl_fptype gbs = m_D_BS.G();
#else
const nl_fptype IeqBS = 0.0;
const nl_fptype gbs = 0.0;
const nl_fptype IeqBS = plib::constants<nl_fptype>::zero();
const nl_fptype gbs = plib::constants<nl_fptype>::zero();
#endif
// exchange controlling nodes if necessary
const nl_fptype gsource = is_forward ? (gm + gmb) : 0;
const nl_fptype gdrain = is_forward ? 0.0 : (gm + gmb);
const nl_fptype gsource = is_forward ? (gm + gmb) : plib::constants<nl_fptype>::zero();
const nl_fptype gdrain = is_forward ? plib::constants<nl_fptype>::zero() : (gm + gmb);
const nl_fptype IeqDS = (is_forward) ?
Ids - gm * Vgs - gmb * Vbs - gds * Vds
: -Ids - gm * Vgd - gmb * Vbd - gds * Vds;
// IG = 0
nl_fptype IG = 0.0;
nl_fptype IG = plib::constants<nl_fptype>::zero();
nl_fptype ID = (+IeqBD - IeqDS) * m_polarity;
nl_fptype IS = (+IeqBS + IeqDS) * m_polarity;
nl_fptype IB = (-IeqBD - IeqBS) * m_polarity;
nl_fptype gGG = 0.0;
nl_fptype gGD = 0.0;
nl_fptype gGS = 0.0;
nl_fptype gGB = 0.0;
nl_fptype gGG = plib::constants<nl_fptype>::zero();
nl_fptype gGD = plib::constants<nl_fptype>::zero();
nl_fptype gGS = plib::constants<nl_fptype>::zero();
nl_fptype gGB = plib::constants<nl_fptype>::zero();
nl_fptype gDG = gm;
nl_fptype gDD = gds + gbd - gdrain;
@ -556,7 +559,7 @@ namespace analog
nl_fptype gSS = gbs + gds + gsource;
const nl_fptype gSB = -gbs - gmb;
nl_fptype gBG = 0.0;
nl_fptype gBG = plib::constants<nl_fptype>::zero();
const nl_fptype gBD = -gbd;
const nl_fptype gBS = -gbs;
nl_fptype gBB = gbs + gbd;
@ -577,16 +580,16 @@ namespace analog
// Source connected to body, Diode S-B shorted!
const nl_fptype gSSBB = gSS + gBB + gBS + gSB;
const auto zero(plib::constants<nl_fptype>::zero());
// S G
m_SG.set_mat( gSSBB, gSG + gBG, +(IS + IB), // S
gGS + gGB, gGG, IG ); // G
// D G
m_DG.set_mat( gDD, gDG, +ID, // D
gGD, 0.0, 0.0 ); // G
gGD, zero, zero ); // G
// S D
m_SD.set_mat( 0.0, gSD + gBD, 0.0, // S
gDS + gDB, 0.0, 0.0); // D
m_SD.set_mat( zero, gSD + gBD, zero, // S
gDS + gDB, zero, zero); // D
}
NETLIB_UPDATE_PARAM(MOSFET)

View File

@ -197,13 +197,13 @@ namespace netlist
NETLIB_UPDATE(opamp)
{
const nl_fptype cVt = 0.0258 * 1.0; // * m_n;
const nl_fptype cVt = plib::constants<nl_fptype>::cast(0.0258 * 1.0); // * m_n;
const nl_fptype cId = m_model.m_DAB; // 3 mA
const nl_fptype cVd = cVt * std::log(cId / 1e-15 + 1.0);
const nl_fptype cVd = cVt * std::log(cId / plib::constants<nl_fptype>::cast(1e-15) + plib::constants<nl_fptype>::one());
m_VH.push(m_VCC() - m_model.m_VLH - cVd);
m_VL.push(m_GND() + m_model.m_VLL + cVd);
m_VREF.push((m_VCC() + m_GND()) / 2.0);
m_VREF.push((m_VCC() + m_GND()) / plib::constants<nl_fptype>::two());
}
NETLIB_UPDATE_PARAM(opamp)
@ -220,11 +220,11 @@ namespace netlist
if (m_type == 3 || m_type == 2)
{
nl_fptype CP = m_model.m_DAB / m_model.m_SLEW;
nl_fptype RP = 0.5 / constants::pi() / CP / m_model.m_FPF;
nl_fptype RP = plib::constants<nl_fptype>::half() / constants::pi() / CP / m_model.m_FPF;
nl_fptype G = m_model.m_UGF / m_model.m_FPF / RP;
//printf("OPAMP %s: %g %g %g\n", name().c_str(), CP, RP, G);
if (m_model.m_SLEW / (4.0 * constants::pi() * 0.0258) < m_model.m_UGF)
if (m_model.m_SLEW / (plib::constants<nl_fptype>::four() * constants::pi() * plib::constants<nl_fptype>::cast(0.0258)) < m_model.m_UGF)
log().warning(MW_OPAMP_FAIL_CONVERGENCE(this->name()));
m_CP->m_C.setTo(CP);
@ -234,12 +234,12 @@ namespace netlist
}
if (m_type == 2)
{
m_EBUF->m_G.setTo(1.0);
m_EBUF->m_G.setTo(plib::constants<nl_fptype>::one());
m_EBUF->m_RO.setTo(m_model.m_RO);
}
if (m_type == 3)
{
m_EBUF->m_G.setTo(1.0);
m_EBUF->m_G.setTo(plib::constants<nl_fptype>::one());
m_EBUF->m_RO.setTo(m_model.m_RO);
}
}

View File

@ -13,7 +13,7 @@
/* FIXME : convert to parameters */
#define R_OFF (plib::reciprocal(exec().gmin()))
#define R_ON 0.01
#define R_ON plib::constants<nl_fptype>::cast(0.01)
namespace netlist
{

View File

@ -53,15 +53,15 @@
#warning "Do not include rescap.h in a netlist environment"
#endif
#ifndef RES_R
#define RES_R(res) (static_cast<nl_fptype>(res))
#define RES_K(res) (static_cast<nl_fptype>(res) * 1e3)
#define RES_M(res) (static_cast<nl_fptype>(res) * 1e6)
#define CAP_U(cap) (static_cast<nl_fptype>(cap) * 1e-6)
#define CAP_N(cap) (static_cast<nl_fptype>(cap) * 1e-9)
#define CAP_P(cap) (static_cast<nl_fptype>(cap) * 1e-12)
#define IND_U(ind) (static_cast<nl_fptype>(ind) * 1e-6)
#define IND_N(ind) (static_cast<nl_fptype>(ind) * 1e-9)
#define IND_P(ind) (static_cast<nl_fptype>(ind) * 1e-12)
#define RES_R(res) (res)
#define RES_K(res) ((res) * 1e3)
#define RES_M(res) ((res) * 1e6)
#define CAP_U(cap) ((cap) * 1e-6)
#define CAP_N(cap) ((cap) * 1e-9)
#define CAP_P(cap) ((cap) * 1e-12)
#define IND_U(ind) ((ind) * 1e-6)
#define IND_N(ind) ((ind) * 1e-9)
#define IND_P(ind) ((ind) * 1e-12)
#endif
#endif /* NLD_TWOTERM_H_ */

View File

@ -67,16 +67,17 @@ NETLIB_UPDATE_TERMINALS(LVCCS)
{
const nl_fptype m_mult = m_G() * m_gfac; // 1.0 ==> 1V ==> 1A
const nl_fptype vi = m_IP.net().Q_Analog() - m_IN.net().Q_Analog();
const auto c1(plib::constants<nl_fptype>::cast(0.2));
if (std::abs(m_mult / m_cur_limit() * vi) > 0.5)
m_vi = m_vi + 0.2*std::tanh((vi - m_vi)/0.2);
if (std::abs(m_mult / m_cur_limit() * vi) > plib::constants<nl_fptype>::half())
m_vi = m_vi + c1 * std::tanh((vi - m_vi) / c1);
else
m_vi = vi;
const nl_fptype x = m_mult / m_cur_limit() * m_vi;
const nl_fptype X = std::tanh(x);
const nl_fptype beta = m_mult * (1.0 - X*X);
const nl_fptype beta = m_mult * (plib::constants<nl_fptype>::one() - X*X);
const nl_fptype I = m_cur_limit() * X - beta * m_vi;
m_OP.set_go_gt_I(-beta, plib::constants<nl_fptype>::zero(), I);

View File

@ -39,15 +39,15 @@ namespace netlist {
{
public:
NETLIB_CONSTRUCTOR(VCCS)
, m_G(*this, "G", 1.0)
, m_RI(*this, "RI", 1e9)
, m_G(*this, "G", plib::constants<nl_fptype>::one())
, m_RI(*this, "RI", plib::constants<nl_fptype>::cast(1e9))
, m_OP(*this, "OP", &m_IP)
, m_ON(*this, "ON", &m_IP)
, m_IP(*this, "IP", &m_IN) // <= this should be NULL and terminal be filtered out prior to solving...
, m_IN(*this, "IN", &m_IP) // <= this should be NULL and terminal be filtered out prior to solving...
, m_OP1(*this, "_OP1", &m_IN)
, m_ON1(*this, "_ON1", &m_IN)
, m_gfac(1.0)
, m_gfac(plib::constants<nl_fptype>::one())
{
connect(m_OP, m_OP1);
connect(m_ON, m_ON1);
@ -85,8 +85,8 @@ namespace netlist {
{
public:
NETLIB_CONSTRUCTOR_DERIVED(LVCCS, VCCS)
, m_cur_limit(*this, "CURLIM", 1000.0)
, m_vi(0.0)
, m_cur_limit(*this, "CURLIM", plib::constants<nl_fptype>::cast(1000.0))
, m_vi(plib::constants<nl_fptype>::zero())
{
}
@ -174,7 +174,7 @@ namespace netlist {
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VCVS, VCCS)
, m_RO(*this, "RO", 1.0)
, m_RO(*this, "RO", plib::constants<nl_fptype>::one())
, m_OP2(*this, "_OP2", &m_ON2)
, m_ON2(*this, "_ON2", &m_OP2)
{

View File

@ -64,7 +64,7 @@ NETLIB_RESET(POT)
{
nl_fptype v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
v = (std::exp(v) - plib::constants<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one());
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
m_R2.set_R(std::max(m_R() * (plib::constants<nl_fptype>::one() - v), exec().gmin()));
@ -77,9 +77,9 @@ NETLIB_UPDATE_PARAM(POT)
nl_fptype v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
v = (std::exp(v) - plib::constants<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one());
if (m_Reverse())
v = 1.0 - v;
v = plib::constants<nl_fptype>::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
m_R2.set_R(std::max(m_R() * (plib::constants<nl_fptype>::one() - v), exec().gmin()));
@ -94,9 +94,9 @@ NETLIB_RESET(POT2)
nl_fptype v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
v = (std::exp(v) - plib::constants<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one());
if (m_Reverse())
v = 1.0 - v;
v = plib::constants<nl_fptype>::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
}
@ -108,9 +108,9 @@ NETLIB_UPDATE_PARAM(POT2)
nl_fptype v = m_Dial();
if (m_DialIsLog())
v = (std::exp(v) - 1.0) / (std::exp(1.0) - 1.0);
v = (std::exp(v) - plib::constants<nl_fptype>::one()) / (std::exp(plib::constants<nl_fptype>::one()) - plib::constants<nl_fptype>::one());
if (m_Reverse())
v = 1.0 - v;
v = plib::constants<nl_fptype>::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
}
@ -121,7 +121,7 @@ NETLIB_UPDATE_PARAM(POT2)
NETLIB_RESET(L)
{
m_gmin = exec().gmin();
m_I = 0.0;
m_I = plib::constants<nl_fptype>::zero();
m_G = m_gmin;
set_mat( m_G, -m_G, -m_I,
-m_G, m_G, m_I);
@ -152,7 +152,7 @@ NETLIB_RESET(D)
nl_fptype n = m_model.m_N;
m_D.set_param(Is, n, exec().gmin(), constants::T0());
set_G_V_I(m_D.G(), 0.0, m_D.Ieq());
set_G_V_I(m_D.G(), plib::constants<nl_fptype>::zero(), m_D.Ieq());
}
NETLIB_UPDATE_PARAM(D)

View File

@ -128,8 +128,8 @@ namespace analog
void set_R(const nl_fptype R)
{
const nl_fptype G = plib::constants<nl_fptype>::one() / R;
set_mat( G, -G, 0.0,
-G, G, 0.0);
set_mat( G, -G, plib::constants<nl_fptype>::zero(),
-G, G, plib::constants<nl_fptype>::zero());
}
NETLIB_RESETI();
@ -142,7 +142,7 @@ namespace analog
NETLIB_OBJECT_DERIVED(R, R_base)
{
NETLIB_CONSTRUCTOR_DERIVED(R, R_base)
, m_R(*this, "R", 1e9)
, m_R(*this, "R", plib::constants<nl_fptype>::cast(1e9))
{
}
@ -178,7 +178,7 @@ namespace analog
, m_R1(*this, "_R1")
, m_R2(*this, "_R2")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_Dial(*this, "DIAL", plib::constants<nl_fptype>::half())
, m_DialIsLog(*this, "DIALLOG", false)
, m_Reverse(*this, "REVERSE", false)
{
@ -208,8 +208,8 @@ namespace analog
{
NETLIB_CONSTRUCTOR(POT2)
, m_R1(*this, "_R1")
, m_R(*this, "R", 10000)
, m_Dial(*this, "DIAL", 0.5)
, m_R(*this, "R", plib::constants<nl_fptype>::cast(10000.0))
, m_Dial(*this, "DIAL", plib::constants<nl_fptype>::half())
, m_DialIsLog(*this, "DIALLOG", false)
, m_Reverse(*this, "REVERSE", false)
{
@ -239,7 +239,7 @@ namespace analog
{
public:
NETLIB_CONSTRUCTOR_DERIVED(C, twoterm)
, m_C(*this, "C", 1e-6)
, m_C(*this, "C", plib::constants<nl_fptype>::cast(1e-6))
, m_cap(*this, "m_cap")
{
}
@ -289,10 +289,10 @@ namespace analog
{
public:
NETLIB_CONSTRUCTOR_DERIVED(L, twoterm)
, m_L(*this, "L", 1e-6)
, m_gmin(0.0)
, m_G(0.0)
, m_I(0.0)
, m_L(*this, "L", plib::constants<nl_fptype>::cast(1e-6))
, m_gmin(plib::constants<nl_fptype>::zero())
, m_G(plib::constants<nl_fptype>::zero())
, m_I(plib::constants<nl_fptype>::zero())
{
//register_term("1", m_P);
//register_term("2", m_N);
@ -392,12 +392,12 @@ namespace analog
{
public:
NETLIB_CONSTRUCTOR_DERIVED(VS, twoterm)
, m_t(*this, "m_t", 0.0)
, m_R(*this, "R", 0.1)
, m_V(*this, "V", 0.0)
, m_t(*this, "m_t", plib::constants<nl_fptype>::zero())
, m_R(*this, "R", plib::constants<nl_fptype>::cast(0.1))
, m_V(*this, "V", plib::constants<nl_fptype>::zero())
, m_func(*this,"FUNC", "")
, m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
, m_funcparam({0.0})
, m_funcparam({plib::constants<nl_fptype>::zero()})
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@ -413,7 +413,7 @@ namespace analog
m_funcparam[0] = m_t;
this->set_G_V_I(plib::reciprocal(m_R()),
m_compiled.evaluate(m_funcparam),
0.0);
plib::constants<nl_fptype>::zero());
}
protected:
@ -422,7 +422,7 @@ namespace analog
NETLIB_RESETI()
{
NETLIB_NAME(twoterm)::reset();
this->set_G_V_I(plib::reciprocal(m_R()), m_V(), 0.0);
this->set_G_V_I(plib::reciprocal(m_R()), m_V(), plib::constants<nl_fptype>::zero());
}
private:
@ -442,11 +442,11 @@ namespace analog
{
public:
NETLIB_CONSTRUCTOR_DERIVED(CS, twoterm)
, m_t(*this, "m_t", 0.0)
, m_I(*this, "I", 1.0)
, m_t(*this, "m_t", plib::constants<nl_fptype>::zero())
, m_I(*this, "I", plib::constants<nl_fptype>::one())
, m_func(*this,"FUNC", "")
, m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
, m_funcparam({0.0})
, m_funcparam({plib::constants<nl_fptype>::zero()})
{
register_subalias("P", m_P);
register_subalias("N", m_N);
@ -460,8 +460,9 @@ namespace analog
m_t += step;
m_funcparam[0] = m_t;
const nl_fptype I = m_compiled.evaluate(m_funcparam);
set_mat(0.0, 0.0, -I,
0.0, 0.0, I);
const auto zero(plib::constants<nl_fptype>::zero());
set_mat(zero, zero, -I,
zero, zero, I);
}
protected:
@ -470,15 +471,17 @@ namespace analog
NETLIB_RESETI()
{
NETLIB_NAME(twoterm)::reset();
set_mat(0.0, 0.0, -m_I(),
0.0, 0.0, m_I());
const auto zero(plib::constants<nl_fptype>::zero());
set_mat(zero, zero, -m_I(),
zero, zero, m_I());
}
NETLIB_UPDATE_PARAMI()
{
solve_now();
set_mat(0.0, 0.0, -m_I(),
0.0, 0.0, m_I());
const auto zero(plib::constants<nl_fptype>::zero());
set_mat(zero, zero, -m_I(),
zero, zero, m_I());
}

View File

@ -22,7 +22,7 @@ namespace netlist
, m_supply(*this, "VDD", "VSS", true)
, m_R(*this, "R")
, m_control(*this, "CTL")
, m_base_r(*this, "BASER", 270.0)
, m_base_r(*this, "BASER", plib::constants<nl_fptype>::cast(270.0))
{
}
@ -52,7 +52,7 @@ namespace netlist
nl_fptype high = plib::constants<nl_fptype>::cast(0.55) * sup;
nl_fptype in = m_control() - m_supply.GND();
nl_fptype rON = m_base_r() * plib::constants<nl_fptype>::cast(5.0) / sup;
nl_fptype R = -1.0;
nl_fptype R = -plib::constants<nl_fptype>::one();
if (in < low)
{

View File

@ -20,7 +20,7 @@ namespace netlist { namespace devices {
, m_R(*this, "_R")
, m_S(*this, "S")
, m_E(*this, "E")
, m_base_r(*this, "BASER", 45.0)
, m_base_r(*this, "BASER", plib::constants<nl_fptype>::cast(45.0))
{
}

View File

@ -31,8 +31,8 @@ namespace netlist
, m_last_trig(*this, "m_last_trig", 0)
, m_state(*this, "m_state", 0)
, m_KP(*this, "m_KP", 0)
, m_K(*this, "K", (m_dev_type == 4538) ? 1.0 : 0.4) // CD4538 datasheet states PW=RC
, m_RI(*this, "RI", 400.0) // around 250 for HC series, 400 on LS/TTL, estimated from datasheets
, m_K(*this, "K", plib::constants<nl_fptype>::cast((m_dev_type == 4538) ? 1.0 : 0.4)) // CD4538 datasheet states PW=RC
, m_RI(*this, "RI", plib::constants<nl_fptype>::cast(400.0)) // around 250 for HC series, 400 on LS/TTL, estimated from datasheets
{
if ((m_dev_type != 9602) && (m_dev_type != 4538) )
m_dev_type = 74123;
@ -241,7 +241,7 @@ namespace netlist
}
if (m_state == 2)
{
const nl_fptype vHigh = m_RP.m_R.m_P() * (1.0 - m_KP);
const nl_fptype vHigh = m_RP.m_R.m_P() * (plib::constants<nl_fptype>::one() - m_KP);
if (m_CV() > vHigh)
{
m_RP_Q.push(0, NLTIME_FROM_NS(10)); // R_OFF
@ -255,7 +255,7 @@ namespace netlist
NETLIB_RESET(74123)
{
m_KP = plib::reciprocal(1.0 + exp(m_K()));
m_KP = plib::reciprocal(plib::constants<nl_fptype>::one() + std::exp(m_K()));
m_RP.reset();
m_RN.reset();

View File

@ -85,7 +85,7 @@ namespace netlist
, m_ENQ(*this, "ENQ")
, m_RNG(*this, "RNG")
, m_FC(*this, "FC")
, m_CAP(*this, "CAP", 1e-6)
, m_CAP(*this, "CAP", plib::constants<nl_fptype>::cast(1e-6))
{
register_subalias("GND", m_R_FC.m_N);
@ -98,8 +98,8 @@ namespace netlist
NETLIB_RESETI()
{
m_R_FC.set_R(90000.0);
m_R_RNG.set_R(90000.0);
m_R_FC.set_R( plib::constants<nl_fptype>::cast(90000.0));
m_R_RNG.set_R(plib::constants<nl_fptype>::cast(90000.0));
m_clock.reset();
}
NETLIB_UPDATEI();
@ -179,16 +179,16 @@ namespace netlist
nl_fptype v_rng = m_RNG();
/* coefficients */
const nl_fptype k1 = 1.9904769024796283E+03;
const nl_fptype k2 = 1.2070059213983407E+03;
const nl_fptype k3 = 1.3266985579561108E+03;
const nl_fptype k4 = -1.5500979825922698E+02;
const nl_fptype k5 = 2.8184536266938172E+00;
const nl_fptype k6 = -2.3503421582744556E+02;
const nl_fptype k7 = -3.3836786704527788E+02;
const nl_fptype k8 = -1.3569136703258670E+02;
const nl_fptype k9 = 2.9914575453819188E+00;
const nl_fptype k10 = 1.6855569086173170E+00;
const nl_fptype k1 = plib::constants<nl_fptype>::cast( 1.9904769024796283E+03);
const nl_fptype k2 = plib::constants<nl_fptype>::cast( 1.2070059213983407E+03);
const nl_fptype k3 = plib::constants<nl_fptype>::cast( 1.3266985579561108E+03);
const nl_fptype k4 = plib::constants<nl_fptype>::cast(-1.5500979825922698E+02);
const nl_fptype k5 = plib::constants<nl_fptype>::cast( 2.8184536266938172E+00);
const nl_fptype k6 = plib::constants<nl_fptype>::cast(-2.3503421582744556E+02);
const nl_fptype k7 = plib::constants<nl_fptype>::cast(-3.3836786704527788E+02);
const nl_fptype k8 = plib::constants<nl_fptype>::cast(-1.3569136703258670E+02);
const nl_fptype k9 = plib::constants<nl_fptype>::cast( 2.9914575453819188E+00);
const nl_fptype k10 = plib::constants<nl_fptype>::cast( 1.6855569086173170E+00);
/* scale due to input resistance */
@ -212,7 +212,7 @@ namespace netlist
// FIXME: we need a possibility to remove entries from queue ...
// or an exact model ...
m_clock.m_inc = netlist_time::from_fp<nl_fptype>(0.5 / freq);
m_clock.m_inc = netlist_time::from_fp(plib::constants<nl_fptype>::half() / freq);
//m_clock.update();
//NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq));

View File

@ -69,9 +69,11 @@ namespace netlist
{
//m_V0.initial(0.0);
//m_RV.do_reset();
m_RV.set_G_V_I(plib::constants<nl_fptype>::one() / R_LOW, 0.0, 0.0);
m_RV.set_G_V_I(plib::constants<nl_fptype>::one() / plib::constants<nl_fptype>::cast(R_LOW),
plib::constants<nl_fptype>::zero(),
plib::constants<nl_fptype>::zero());
m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ()));
if (m_FREQ() < 24000 || m_FREQ() > 56000)
if (m_FREQ() < plib::constants<nl_fptype>::cast(24000) || m_FREQ() > plib::constants<nl_fptype>::cast(56000))
log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ()));
m_shift = 0x1ffff;
@ -81,7 +83,7 @@ namespace netlist
NETLIB_UPDATE_PARAM(MM5837_dip)
{
m_inc = netlist_time::from_fp(plib::reciprocal(m_FREQ()));
if (m_FREQ() < 24000 || m_FREQ() > 56000)
if (m_FREQ() < plib::constants<nl_fptype>::cast(24000) || m_FREQ() > plib::constants<nl_fptype>::cast(56000))
log().warning(MW_FREQUENCY_OUTSIDE_OF_SPECS_1(m_FREQ()));
}
@ -102,7 +104,7 @@ namespace netlist
if (state != last_state)
{
const nl_fptype R = state ? R_HIGH : R_LOW;
const nl_fptype R = plib::constants<nl_fptype>::cast(state ? R_HIGH : R_LOW);
const nl_fptype V = state ? m_VDD() : m_VSS();
// We only need to update the net first if this is a time stepping net

View File

@ -140,11 +140,11 @@ namespace netlist
m_RDIS.reset();
/* FIXME make resistances a parameter, properly model other variants */
m_R1.set_R(5000);
m_R2.set_R(5000);
m_R3.set_R(5000);
m_ROUT.set_R(20);
m_RDIS.set_R(R_OFF);
m_R1.set_R(plib::constants<nl_fptype>::cast(5000));
m_R2.set_R(plib::constants<nl_fptype>::cast(5000));
m_R3.set_R(plib::constants<nl_fptype>::cast(5000));
m_ROUT.set_R(plib::constants<nl_fptype>::cast(20));
m_RDIS.set_R(plib::constants<nl_fptype>::cast(R_OFF));
m_last_out = true;
}
@ -161,9 +161,9 @@ namespace netlist
}
else
{
const nl_fptype vt = clamp(m_R2.m_P(), 0.7, 1.4);
const nl_fptype vt = clamp(m_R2.m_P(), plib::constants<nl_fptype>::cast(0.7), plib::constants<nl_fptype>::cast(1.4));
const bool bthresh = (m_THRES() > vt);
const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), 0.7, 1.4));
const bool btrig = (m_TRIG() > clamp(m_R2.m_N(), plib::constants<nl_fptype>::cast(0.7), plib::constants<nl_fptype>::cast(1.4)));
if (!btrig)
m_ff = true;
@ -177,14 +177,14 @@ namespace netlist
{
m_RDIS.update();
m_OUT.push(m_R3.m_N());
m_RDIS.set_R(R_ON);
m_RDIS.set_R(plib::constants<nl_fptype>::cast(R_ON));
}
else if (!m_last_out && out)
{
m_RDIS.update();
// FIXME: Should be delayed by 100ns
m_OUT.push(m_R1.m_P());
m_RDIS.set_R(R_OFF);
m_RDIS.set_R(plib::constants<nl_fptype>::cast(R_OFF));
}
m_last_reset = reset;
m_last_out = out;

View File

@ -16,8 +16,8 @@ namespace netlist
NETLIB_OBJECT_DERIVED(r2r_dac, twoterm)
{
NETLIB_CONSTRUCTOR_DERIVED(r2r_dac, twoterm)
, m_VIN(*this, "VIN", 1.0)
, m_R(*this, "R", 1.0)
, m_VIN(*this, "VIN", plib::constants<nl_fptype>::one())
, m_R(*this, "R", plib::constants<nl_fptype>::one())
, m_num(*this, "N", 1)
, m_val(*this, "VAL", 1)
{
@ -44,7 +44,7 @@ namespace netlist
nl_fptype V = m_VIN() / static_cast<nl_fptype>(1 << m_num())
* static_cast<nl_fptype>(m_val());
this->set_G_V_I(plib::reciprocal(m_R()), V, 0.0);
this->set_G_V_I(plib::reciprocal(m_R()), V, plib::constants<nl_fptype>::zero());
}
} //namespace analog

View File

@ -85,8 +85,8 @@ namespace netlist
m_RVI.reset();
m_RVO.reset();
m_is_timestep = m_RVO.m_P.net().solver()->has_timestep_devices();
m_RVI.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_RI, m_model.m_VI, 0.0);
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, 0.0);
m_RVI.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_RI, m_model.m_VI, plib::constants<nl_fptype>::zero());
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, plib::constants<nl_fptype>::zero());
}
NETLIB_UPDATEI()
@ -98,7 +98,7 @@ namespace netlist
m_last_state = 0;
if (m_is_timestep)
m_RVO.update();
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROH, m_model.m_VOH, 0.0);
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROH, m_model.m_VOH, plib::constants<nl_fptype>::zero());
m_RVO.solve_later();
}
}
@ -109,7 +109,7 @@ namespace netlist
m_last_state = 1;
if (m_is_timestep)
m_RVO.update();
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, 0.0);
m_RVO.set_G_V_I(plib::constants<nl_fptype>::one() / m_model.m_ROL, m_model.m_VOL, plib::constants<nl_fptype>::zero());
m_RVO.solve_later();
}
}

View File

@ -52,11 +52,11 @@ namespace netlist
nl_assert(m_logic_family != nullptr);
// FIXME: Variable supply voltage!
nl_fptype supply_V = logic_family()->fixed_V();
if (supply_V == 0.0) supply_V = 5.0;
if (supply_V == plib::constants<nl_fptype>::zero()) supply_V = plib::constants<nl_fptype>::cast(5.0);
if (m_I.Q_Analog() > logic_family()->high_thresh_V(0.0, supply_V))
if (m_I.Q_Analog() > logic_family()->high_thresh_V(plib::constants<nl_fptype>::zero(), supply_V))
out().push(1, netlist_time::quantum());
else if (m_I.Q_Analog() < logic_family()->low_thresh_V(0.0, supply_V))
else if (m_I.Q_Analog() < logic_family()->low_thresh_V(plib::constants<nl_fptype>::zero(), supply_V))
out().push(0, netlist_time::quantum());
else
{
@ -112,7 +112,7 @@ namespace netlist
//FIXME: Use power terminals and change info to warning or error
if (!f)
{
if (logic_family()->fixed_V() == 0.0)
if (logic_family()->fixed_V() == plib::constants<nl_fptype>::zero())
log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name())));
else
log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name())));
@ -148,7 +148,9 @@ namespace netlist
{
// FIXME: Variable voltage
nl_fptype supply_V = logic_family()->fixed_V();
if (supply_V == 0.0) supply_V = 5.0;
// FIXME: comparison to zero
if (supply_V == plib::constants<nl_fptype>::zero())
supply_V = plib::constants<nl_fptype>::cast(5.0);
//m_Q.initial(0.0);
m_last_state = -1;
@ -160,9 +162,10 @@ namespace netlist
m_VCCHack->initial(supply_V);
m_is_timestep = m_RN.m_P.net().solver()->has_timestep_devices();
m_RN.set_G_V_I(plib::constants<nl_fptype>::one() / logic_family()->R_low(),
logic_family()->low_offset_V(), 0.0);
logic_family()->low_offset_V(), plib::constants<nl_fptype>::zero());
m_RP.set_G_V_I(G_OFF,
0.0, 0.0);
plib::constants<nl_fptype>::zero(),
plib::constants<nl_fptype>::zero());
}
NETLIB_UPDATE(d_to_a_proxy)
@ -178,16 +181,18 @@ namespace netlist
if (state)
{
m_RN.set_G_V_I(G_OFF,
0.0, 0.0);
plib::constants<nl_fptype>::zero(),
plib::constants<nl_fptype>::zero());
m_RP.set_G_V_I(plib::constants<nl_fptype>::one() / logic_family()->R_high(),
logic_family()->high_offset_V(), 0.0);
logic_family()->high_offset_V(), plib::constants<nl_fptype>::zero());
}
else
{
m_RN.set_G_V_I(plib::constants<nl_fptype>::one() / logic_family()->R_low(),
logic_family()->low_offset_V(), 0.0);
logic_family()->low_offset_V(), plib::constants<nl_fptype>::zero());
m_RP.set_G_V_I(G_OFF,
0.0, 0.0);
plib::constants<nl_fptype>::zero(),
plib::constants<nl_fptype>::zero());
}
m_RN.solve_later(); // RN, RP are connected ...
m_last_state = state;

View File

@ -104,7 +104,7 @@ namespace netlist
private:
static constexpr const nl_fptype G_OFF = 1e-9;
static constexpr const nl_fptype G_OFF = plib::constants<nl_fptype>::cast(1e-9);
plib::unique_ptr<analog_output_t> m_GNDHack; // FIXME: Long term, we need to connect proxy gnd to device gnd
plib::unique_ptr<analog_output_t> m_VCCHack; // FIXME: Long term, we need to connect proxy gnd to device gnd

View File

@ -52,9 +52,9 @@ namespace devices
{
NETLIB_CONSTRUCTOR(mainclock)
, m_Q(*this, "Q")
, m_freq(*this, "FREQ", 7159000.0 * 5)
, m_freq(*this, "FREQ", plib::constants<nl_fptype>::cast(7159000.0 * 5))
{
m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0));
m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
}
NETLIB_RESETI()
@ -64,7 +64,7 @@ namespace devices
NETLIB_UPDATE_PARAMI()
{
m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0));
m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
}
NETLIB_UPDATEI()
@ -91,9 +91,9 @@ namespace devices
NETLIB_CONSTRUCTOR(clock)
, m_feedback(*this, "FB")
, m_Q(*this, "Q")
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
, m_freq(*this, "FREQ", plib::constants<nl_fptype>::cast(7159000.0 * 5.0))
{
m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0));
m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
connect(m_feedback, m_Q);
}
@ -101,7 +101,7 @@ namespace devices
NETLIB_UPDATE_PARAMI()
{
m_inc = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq() * 2.0));
m_inc = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
}
NETLIB_UPDATEI()
@ -128,7 +128,7 @@ namespace devices
, m_Q(*this, "Q")
, m_func(*this,"FUNC", "")
, m_compiled(this->name() + ".FUNCC", this, this->state().run_state_manager())
, m_funcparam({0.0})
, m_funcparam({plib::constants<nl_fptype>::zero()})
{
if (m_func() != "")
m_compiled.compile(std::vector<pstring>({{pstring("T")}}), m_func());
@ -160,19 +160,19 @@ namespace devices
NETLIB_OBJECT(extclock)
{
NETLIB_CONSTRUCTOR(extclock)
, m_freq(*this, "FREQ", 7159000.0 * 5.0)
, m_freq(*this, "FREQ", plib::constants<nl_fptype>::cast(7159000.0 * 5.0))
, m_pattern(*this, "PATTERN", "1,1")
, m_offset(*this, "OFFSET", 0.0)
, m_offset(*this, "OFFSET", plib::constants<nl_fptype>::zero())
, m_feedback(*this, "FB")
, m_Q(*this, "Q")
, m_cnt(*this, "m_cnt", 0)
, m_off(*this, "m_off", netlist_time::zero())
{
m_inc[0] = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq() * 2.0));
m_inc[0] = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
connect(m_feedback, m_Q);
netlist_time base = netlist_time::from_fp<decltype(m_freq())>(1.0 / (m_freq()*2.0));
netlist_time base = netlist_time::from_fp(plib::reciprocal(m_freq()*plib::constants<nl_fptype>::two()));
std::vector<pstring> pat(plib::psplit(m_pattern(),","));
m_off = netlist_time::from_fp(m_offset());
@ -250,12 +250,12 @@ namespace devices
{
NETLIB_CONSTRUCTOR(analog_input)
, m_Q(*this, "Q")
, m_IN(*this, "IN", 0.0)
, m_IN(*this, "IN", plib::constants<nl_fptype>::zero())
{
}
NETLIB_UPDATEI() { }
NETLIB_RESETI() { m_Q.initial(0.0); }
NETLIB_RESETI() { m_Q.initial(plib::constants<nl_fptype>::zero()); }
NETLIB_UPDATE_PARAMI() { m_Q.push(m_IN()); }
private:
@ -275,7 +275,7 @@ namespace devices
}
NETLIB_UPDATEI()
{
m_Q.push(0.0);
m_Q.push(plib::constants<nl_fptype>::zero());
}
NETLIB_RESETI() { }
protected:
@ -316,8 +316,8 @@ namespace devices
, m_ROUT(*this, "m_ROUT", true)
, m_I(*this, "_I")
, m_Q(*this, "_Q")
, m_p_RIN(*this, "RIN", 1.0e6)
, m_p_ROUT(*this, "ROUT", 50.0)
, m_p_RIN(*this, "RIN", plib::constants<nl_fptype>::cast(1.0e6))
, m_p_ROUT(*this, "ROUT", plib::constants<nl_fptype>::cast(50.0))
{
register_subalias("I", m_RIN.m_P);
@ -371,7 +371,7 @@ namespace devices
pstring n = plib::pfmt("A{1}")(i);
m_I.push_back(pool().make_unique<analog_input_t>(*this, n));
inps.push_back(n);
m_vals.push_back(0.0);
m_vals.push_back(plib::constants<nl_fptype>::zero());
}
m_compiled.compile(inps, m_func());
}
@ -402,8 +402,8 @@ namespace devices
NETLIB_CONSTRUCTOR(res_sw)
, m_R(*this, "_R")
, m_I(*this, "I")
, m_RON(*this, "RON", 1.0)
, m_ROFF(*this, "ROFF", 1.0E20)
, m_RON(*this, "RON", plib::constants<nl_fptype>::one())
, m_ROFF(*this, "ROFF", plib::constants<nl_fptype>::cast(1.0E20))
, m_last_state(*this, "m_last_state", 0)
{
register_subalias("1", m_R.m_P);

View File

@ -40,14 +40,14 @@ namespace netlist
public:
logic_family_ttl_t() : logic_family_desc_t()
{
m_fixed_V = 5.0;
m_low_thresh_PCNT = 0.8 / 5.0;
m_high_thresh_PCNT = 2.0 / 5.0;
m_fixed_V = plib::constants<nl_fptype>::cast(5.0);
m_low_thresh_PCNT = plib::constants<nl_fptype>::cast(0.8 / 5.0);
m_high_thresh_PCNT = plib::constants<nl_fptype>::cast(2.0 / 5.0);
// m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications.
m_low_VO = 0.1;
m_high_VO = 1.0; // 4.0
m_R_low = 1.0;
m_R_high = 130.0;
m_low_VO = plib::constants<nl_fptype>::cast(0.1);
m_high_VO = plib::constants<nl_fptype>::cast(1.0); // 4.0
m_R_low = plib::constants<nl_fptype>::cast(1.0);
m_R_high = plib::constants<nl_fptype>::cast(130.0);
}
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
@ -67,14 +67,14 @@ namespace netlist
public:
logic_family_cd4xxx_t() : logic_family_desc_t()
{
m_fixed_V = 0.0;
m_low_thresh_PCNT = 1.5 / 5.0;
m_high_thresh_PCNT = 3.5 / 5.0;
m_fixed_V = plib::constants<nl_fptype>::cast(0.0);
m_low_thresh_PCNT = plib::constants<nl_fptype>::cast(1.5 / 5.0);
m_high_thresh_PCNT = plib::constants<nl_fptype>::cast(3.5 / 5.0);
// m_low_V - these depend on sinked/sourced current. Values should be suitable for typical applications.
m_low_VO = 0.05;
m_high_VO = 0.05; // 4.95
m_R_low = 10.0;
m_R_high = 10.0;
m_low_VO = plib::constants<nl_fptype>::cast(0.05);
m_high_VO = plib::constants<nl_fptype>::cast(0.05); // 4.95
m_R_low = plib::constants<nl_fptype>::cast(10.0);
m_R_high = plib::constants<nl_fptype>::cast(10.0);
}
unique_pool_ptr<devices::nld_base_d_to_a_proxy> create_d_a_proxy(netlist_state_t &anetlist, const pstring &name, logic_output_t *proxied) const override;
unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name, logic_input_t *proxied) const override;
@ -669,7 +669,7 @@ namespace netlist
auto *p = dynamic_cast<analog_net_t *>(this);
if (p != nullptr)
p->m_cur_Analog = 0.0;
p->m_cur_Analog = plib::constants<nl_fptype>::zero();
/* rebuild m_list and reset terminals to active or analog out state */
@ -727,7 +727,7 @@ namespace netlist
analog_net_t::analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr)
: net_t(nl, aname, mr)
, m_cur_Analog(*this, "m_cur_Analog", 0.0)
, m_cur_Analog(*this, "m_cur_Analog", plib::constants<nl_fptype>::zero())
, m_solver(nullptr)
{
}

View File

@ -764,12 +764,12 @@ namespace netlist
void set_conductivity(const nl_fptype G) noexcept
{
set_go_gt_I(-G, G, 0.0);
set_go_gt_I(-G, G, plib::constants<nl_fptype>::zero());
}
void set_go_gt(const nl_fptype GO, const nl_fptype GT) noexcept
{
set_go_gt_I(GO, GT, 0.0);
set_go_gt_I(GO, GT, plib::constants<nl_fptype>::zero());
}
void set_go_gt_I(const nl_fptype GO, const nl_fptype GT, const nl_fptype I) noexcept

View File

@ -128,6 +128,7 @@ namespace netlist
static inline constexpr long double TIMESTEP_MINDIV() noexcept { return 1e-60L; }
static inline constexpr const char * name() noexcept { return "long double"; }
static inline constexpr const char * suffix() noexcept { return "L"; }
};
/*! Specific constants for double floating point type
@ -142,6 +143,7 @@ namespace netlist
static inline constexpr double TIMESTEP_MINDIV() noexcept { return 1e-60; }
static inline constexpr const char * name() noexcept { return "double"; }
static inline constexpr const char * suffix() noexcept { return ""; }
};
/*! Specific constants for float floating point type
@ -156,6 +158,7 @@ namespace netlist
static inline constexpr float TIMESTEP_MINDIV() noexcept { return 1e-8f; }
static inline constexpr const char * name() noexcept { return "float"; }
static inline constexpr const char * suffix() noexcept { return "f"; }
};
} // namespace netlist

View File

@ -413,7 +413,15 @@ void parser_t::device(const pstring &dev_type)
nl_fptype parser_t::eval_param(const token_t &tok)
{
static std::array<pstring, 7> macs = {"", "RES_R", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
static std::array<nl_fptype, 7> facs = {1, 1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
static std::array<nl_fptype, 7> facs = {
plib::constants<nl_fptype>::cast(1.0),
plib::constants<nl_fptype>::cast(1.0),
plib::constants<nl_fptype>::cast(1e3),
plib::constants<nl_fptype>::cast(1e6),
plib::constants<nl_fptype>::cast(1e-6),
plib::constants<nl_fptype>::cast(1e-9),
plib::constants<nl_fptype>::cast(1e-12)
};
std::size_t f=0;
nl_fptype ret(0);
@ -423,7 +431,7 @@ nl_fptype parser_t::eval_param(const token_t &tok)
if (f>0)
{
require_token(m_tok_param_left);
ret = get_number_double();
ret = static_cast<nl_fptype>(get_number_double());
require_token(m_tok_param_right);
}
else

View File

@ -119,9 +119,10 @@ namespace netlist
m_namespace_stack.pop();
}
void nlparse_t::register_param(const pstring &param, const nl_fptype value)
void nlparse_t::register_param_x(const pstring &param, const nl_fptype value)
{
if (std::abs(value - std::floor(value)) > 1e-30 || std::abs(value) > 1e9)
if (std::abs(value - std::floor(value)) > plib::constants<nl_fptype>::cast(1e-30)
|| std::abs(value) > plib::constants<nl_fptype>::cast(1e9))
register_param(param, plib::pfmt("{1:.9}").e(value));
else
register_param(param, plib::pfmt("{1}")(static_cast<long>(value)));
@ -945,15 +946,15 @@ nl_fptype models_t::value(const pstring &model, const pstring &entity)
auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1));
switch (*p)
{
case 'M': factor = 1e6; break;
case 'M': factor = plib::constants<nl_fptype>::cast(1e6); break;
case 'k':
case 'K': factor = 1e3; break;
case 'm': factor = 1e-3; break;
case 'u': factor = 1e-6; break;
case 'n': factor = 1e-9; break;
case 'p': factor = 1e-12; break;
case 'f': factor = 1e-15; break;
case 'a': factor = 1e-18; break;
case 'K': factor = plib::constants<nl_fptype>::cast(1e3); break;
case 'm': factor = plib::constants<nl_fptype>::cast(1e-3); break;
case 'u': factor = plib::constants<nl_fptype>::cast(1e-6); break;
case 'n': factor = plib::constants<nl_fptype>::cast(1e-9); break;
case 'p': factor = plib::constants<nl_fptype>::cast(1e-12); break;
case 'f': factor = plib::constants<nl_fptype>::cast(1e-15); break;
case 'a': factor = plib::constants<nl_fptype>::cast(1e-18); break;
default:
if (*p < '0' || *p > '9')
throw nl_exception(MF_UNKNOWN_NUMBER_FACTOR_IN_1(entity));
@ -1125,9 +1126,10 @@ void setup_t::prepare_to_run()
//FIXME: check for errors ...
bool err(false);
auto v = plib::pstonum_ne<nl_fptype>(p->second, err);
if (err || std::abs(v - std::floor(v)) > 1e-6 )
if (err || std::abs(v - std::floor(v)) > plib::constants<nl_fptype>::cast(1e-6) )
log().fatal(MF_HND_VAL_NOT_SUPPORTED(p->second));
d.second->set_hint_deactivate(v == 0.0);
// FIXME comparison with zero
d.second->set_hint_deactivate(v == plib::constants<nl_fptype>::zero());
}
}
else

View File

@ -244,7 +244,16 @@ namespace netlist
void register_link(const pstring &sin, const pstring &sout);
void register_link_arr(const pstring &terms);
void register_param(const pstring &param, const pstring &value);
void register_param(const pstring &param, const nl_fptype value);
// FIXME: quick hack
void register_param_x(const pstring &param, const nl_fptype value);
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value>::type
register_param(const pstring &param, T value)
{
register_param_x(param, static_cast<nl_fptype>(value));
}
void register_lib_entry(const pstring &name, const pstring &sourcefile);
void register_frontier(const pstring &attach, const nl_fptype r_IN, const nl_fptype r_OUT);

View File

@ -216,8 +216,9 @@ namespace plib {
type total() const noexcept { return m_time; }
ctype count() const noexcept { return m_count; }
double as_seconds() const noexcept { return static_cast<double>(total())
/ static_cast<double>(T::per_second()); }
template <typename S>
S as_seconds() const noexcept { return static_cast<S>(total())
/ static_cast<S>(T::per_second()); }
guard_t guard() noexcept { return guard_t(*this); }
private:
@ -247,7 +248,8 @@ namespace plib {
constexpr type average() const noexcept { return 0; }
constexpr type total() const noexcept { return 0; }
constexpr ctype count() const noexcept { return 0; }
constexpr double as_seconds() const noexcept { return 0.0; }
template <typename S>
S as_seconds() const noexcept { return static_cast<S>(0.0); }
constexpr static bool enabled = false;
guard_t guard() { return guard_t(); }
};

View File

@ -195,9 +195,9 @@ namespace plib {
template <typename NT>
NT pfunction<NT>::evaluate(const std::vector<NT> &values) noexcept
{
std::array<NT, 20> stack = { 0 };
std::array<NT, 20> stack = { plib::constants<NT>::zero() };
unsigned ptr = 0;
stack[0] = 0.0;
stack[0] = plib::constants<NT>::zero();
for (auto &rc : m_precompiled)
{
switch (rc.m_cmd)
@ -226,5 +226,6 @@ namespace plib {
template class pfunction<float>;
template class pfunction<double>;
template class pfunction<long double>;
} // namespace plib

View File

@ -10,6 +10,7 @@
#include "pstate.h"
#include "pstring.h"
#include "putil.h"
#include <vector>
@ -42,7 +43,7 @@ namespace plib {
};
struct rpn_inst
{
rpn_inst() : m_cmd(ADD), m_param(0.0) { }
rpn_inst() : m_cmd(ADD), m_param(plib::constants<NT>::zero()) { }
rpn_cmd m_cmd;
NT m_param;
};
@ -116,6 +117,7 @@ namespace plib {
extern template class pfunction<float>;
extern template class pfunction<double>;
extern template class pfunction<long double>;
} // namespace plib

View File

@ -123,7 +123,7 @@ namespace plib
template <typename FT>
static constexpr const typename std::enable_if<std::is_floating_point<FT>::value, ptime>::type
from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(std::floor(t * static_cast<FT>(RES) + 0.5)), RES); }
from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(std::floor(t * static_cast<FT>(RES) + static_cast<FT>(0.5))), RES); }
static constexpr const ptime from_double(const double t) noexcept
{ return from_fp<double>(t); }

View File

@ -221,10 +221,13 @@ namespace plib
struct constants
{
static inline constexpr T zero() noexcept { return static_cast<T>(0); }
static inline constexpr T half() noexcept { return static_cast<T>(0.5); }
static inline constexpr T one() noexcept { return static_cast<T>(1); }
static inline constexpr T two() noexcept { return static_cast<T>(2); }
static inline constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209); }
static inline constexpr T pi() noexcept { return static_cast<T>(3.14159265358979323846264338327950); }
static inline constexpr T three() noexcept { return static_cast<T>(3); }
static inline constexpr T four() noexcept { return static_cast<T>(4); }
static inline constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209L); }
static inline constexpr T pi() noexcept { return static_cast<T>(3.14159265358979323846264338327950L); }
/*!
* \brief Electric constant of vacuum

View File

@ -47,7 +47,7 @@ public:
opt_dir(*this, "d", "dir", "", "output directory for the generated files"),
opt_grp4(*this, "Options for run command", "These options are only used by the run command."),
opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)\n\n abc def\n\n xyz"),
opt_ttr (*this, "t", "time_to_run", 1, "time to run the emulation (seconds)\n\n abc def\n\n xyz"),
opt_stats(*this, "s", "statistics", "gather runtime statistics"),
opt_logs(*this, "l", "log" , "define terminal to log. This option may be specified repeatedly."),
opt_inp(*this, "i", "input", "", "input file to process (default is none)"),
@ -311,7 +311,7 @@ void netlist_tool_callbacks_t::vlog(const plib::plog_level &l, const pstring &ls
struct input_t
{
input_t(const netlist::setup_t &setup, const pstring &line)
: m_value(0.0)
: m_value(plib::constants<nl_fptype>::zero())
{
std::array<char, 400> buf; // NOLINT(cppcoreguidelines-pro-type-member-init)
double t(0);
@ -402,7 +402,7 @@ void tool_app_t::run()
}
pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
pout("startup time ==> {1:5.3f}\n", t.as_seconds<nl_fptype>() );
t.reset();
@ -462,10 +462,10 @@ void tool_app_t::run()
nt.stop();
}
nl_fptype emutime = t.as_seconds();
auto emutime(t.as_seconds<nl_fptype>());
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n",
(ttr - nlt).as_double(), emutime,
(ttr - nlt).as_double() / emutime * 100.0);
(ttr - nlt).as_fp<nl_fptype>(), emutime,
(ttr - nlt).as_fp<nl_fptype>() / emutime * plib::constants<nl_fptype>::cast(100.0));
}
void tool_app_t::validate()

View File

@ -501,7 +501,7 @@ namespace solver
std::vector<bool> touched(1024, false); // FIXME!
nl_fptype weight = 0.0;
nl_fptype weight = plib::constants<nl_fptype>::zero();
auto &term = m_terms[row];
for (std::size_t i = 0; i < term.count(); i++)
{
@ -560,7 +560,7 @@ namespace solver
this->m_stat_calculations,
static_cast<nl_fptype>(this->m_stat_calculations) / this->exec().time().as_fp<nl_fptype>(),
this->m_iterative_fail,
100.0 * static_cast<nl_fptype>(this->m_iterative_fail)
plib::constants<nl_fptype>::cast(100.0) * static_cast<nl_fptype>(this->m_iterative_fail)
/ static_cast<nl_fptype>(this->m_stat_calculations),
static_cast<nl_fptype>(this->m_iterative_total) / static_cast<nl_fptype>(this->m_stat_calculations));
}

View File

@ -49,26 +49,29 @@ namespace solver
struct solver_parameters_t
{
solver_parameters_t(device_t &parent)
: m_freq(parent, "FREQ", 48000.0)
: m_freq(parent, "FREQ", plib::constants<nl_fptype>::cast(48000.0))
/* iteration parameters */
, m_gs_sor(parent, "SOR_FACTOR", 1.059)
, m_method(parent, "METHOD", matrix_type_e::MAT_CR)
, m_fp_type(parent, "FPTYPE", matrix_fp_type_e::DOUBLE)
, m_accuracy(parent, "ACCURACY", 1e-7)
, m_gs_loops(parent, "GS_LOOPS", 9) // Gauss-Seidel loops
, m_gs_sor(parent, "SOR_FACTOR", plib::constants<nl_fptype>::cast(1.059))
, m_method(parent, "METHOD", matrix_type_e::MAT_CR)
, m_fp_type(parent, "FPTYPE", matrix_fp_type_e::DOUBLE)
, m_reltol(parent, "RELTOL", plib::constants<nl_fptype>::cast(1e-3)) ///< SPICE RELTOL parameter
, m_vntol(parent, "VNTOL", plib::constants<nl_fptype>::cast(1e-6)) ///< SPICE VNTOL parameter
, m_accuracy(parent, "ACCURACY", plib::constants<nl_fptype>::cast(1e-7)) ///< Iterative solver accuracy
, m_nr_loops(parent, "NR_LOOPS", 250) ///< Maximum number of Newton-Raphson loops
, m_gs_loops(parent, "GS_LOOPS", 9) ///< Maximum number of Gauss-Seidel loops
/* general parameters */
, m_gmin(parent, "GMIN", 1e-9)
, m_pivot(parent, "PIVOT", false) // use pivoting - on supported solvers
, m_nr_loops(parent, "NR_LOOPS", 250) // Newton-Raphson loops
, m_nr_recalc_delay(parent, "NR_RECALC_DELAY", netlist_time::quantum().as_fp<nl_fptype>()) // Delay to next solve attempt if nr loops exceeded
, m_gmin(parent, "GMIN", plib::constants<nl_fptype>::cast(1e-9))
, m_pivot(parent, "PIVOT", false) ///< use pivoting on supported solvers
, m_nr_recalc_delay(parent, "NR_RECALC_DELAY",
netlist_time::quantum().as_fp<nl_fptype>()) ///< Delay to next solve attempt if nr loops exceeded
, m_parallel(parent, "PARALLEL", 0)
/* automatic time step */
, m_dynamic_ts(parent, "DYNAMIC_TS", false)
, m_dynamic_lte(parent, "DYNAMIC_LTE", 1e-5) // diff/timestep
, m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", 1e-6) // nl_fptype timestep resolution
, m_dynamic_ts(parent, "DYNAMIC_TS", false) ///< Use dynamic time stepping
, m_dynamic_lte(parent, "DYNAMIC_LTE", plib::constants<nl_fptype>::cast(1e-5)) ///< dynamic time stepping slope
, m_dynamic_min_ts(parent, "DYNAMIC_MIN_TIMESTEP", plib::constants<nl_fptype>::cast(1e-6)) ///< smallest time step allowed
/* matrix sorting */
, m_sort_type(parent, "SORT_TYPE", matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT)
@ -95,11 +98,13 @@ namespace solver
param_fp_t m_gs_sor;
param_enum_t<matrix_type_e> m_method;
param_enum_t<matrix_fp_type_e> m_fp_type;
param_fp_t m_reltol;
param_fp_t m_vntol;
param_fp_t m_accuracy;
param_num_t<std::size_t> m_nr_loops;
param_num_t<std::size_t> m_gs_loops;
param_fp_t m_gmin;
param_logic_t m_pivot;
param_num_t<std::size_t> m_nr_loops;
param_fp_t m_nr_recalc_delay;
param_int_t m_parallel;
param_logic_t m_dynamic_ts;
@ -229,31 +234,6 @@ namespace solver
return max_rail;
}
template <typename T>
void store(const T & V)
{
const std::size_t iN = this->m_terms.size();
for (std::size_t i = 0; i < iN; i++)
this->m_terms[i].setV(V[i]);
}
template <typename T>
auto delta(const T & V) -> typename std::decay<decltype(V[0])>::type
{
/* NOTE: Ideally we should also include currents (RHS) here. This would
* need a reevaluation of the right hand side after voltages have been updated
* and thus belong into a different calculation. This applies to all solvers.
*/
const std::size_t iN = this->m_terms.size();
using vtype = typename std::decay<decltype(V[0])>::type;
vtype cerr = 0;
for (std::size_t i = 0; i < iN; i++)
cerr = std::max(cerr, std::abs(V[i] - this->m_terms[i].getV<vtype>()));
return cerr;
}
void set_pointers()
{
const std::size_t iN = this->m_terms.size();
@ -392,6 +372,8 @@ namespace solver
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, nets, params)
, m_dim(size)
, m_new_V(size)
, m_RHS(size)
, m_mat_ptr(size, this->max_railstart() + 1)
, m_last_V(size, plib::constants<nl_fptype>::zero())
, m_DD_n_m_1(size, plib::constants<nl_fptype>::zero())
@ -413,8 +395,15 @@ namespace solver
static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS();
static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8;
PALIGNAS_VECTOROPT()
plib::parray<FT, SIZE> m_new_V;
PALIGNAS_VECTOROPT()
plib::parray<FT, SIZE> m_RHS;
PALIGNAS_VECTOROPT()
plib::parray2D<float_type *, SIZE, 0> m_mat_ptr;
// FIXME: below should be private
/* state - variable time_stepping */
PALIGNAS_VECTOROPT()
plib::parray<nl_fptype, SIZE> m_last_V;
@ -423,7 +412,38 @@ namespace solver
PALIGNAS_VECTOROPT()
plib::parray<nl_fptype, SIZE> m_h_n_m_1;
constexpr std::size_t size() const noexcept { return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim; }
constexpr std::size_t size() const noexcept
{
return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim;
}
void store()
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
this->m_terms[i].setV(m_new_V[i]);
}
bool check_err()
{
/* NOTE: Ideally we should also include currents (RHS) here. This would
* need a reevaluation of the right hand side after voltages have been updated
* and thus belong into a different calculation. This applies to all solvers.
*/
const std::size_t iN = size();
const auto reltol(static_cast<FT>(m_params.m_reltol));
const auto vntol(static_cast<FT>(m_params.m_vntol));
for (std::size_t i = 0; i < iN; i++)
{
const auto vold(this->m_terms[i].template getV<FT>());
const auto vnew(m_new_V[i]);
const auto tol(vntol + reltol * std::max(std::abs(vnew),std::abs(vold)));
if (std::abs(vnew - vold) > tol)
return true;
}
return false;
}
netlist_time compute_next_timestep(const nl_fptype cur_ts) override
{
@ -431,7 +451,7 @@ namespace solver
if (m_params.m_dynamic_ts)
{
for (std::size_t k = 0; k < m_terms.size(); k++)
for (std::size_t k = 0; k < size(); k++)
{
auto &t = m_terms[k];
//const nl_fptype DD_n = (n->Q_Analog() - t->m_last_V);
@ -507,8 +527,7 @@ namespace solver
}
}
template <typename RT>
void fill_matrix(RT &RHS)
void fill_matrix_and_rhs()
{
const std::size_t N = size();
@ -549,7 +568,7 @@ namespace solver
RHS_t += (/*m_Idr[i]*/ (- go[i]) * *cnV[i]);
}
RHS[k] = static_cast<FT>(RHS_t);
m_RHS[k] = static_cast<FT>(RHS_t);
// update diagonal element ...
*tcr_r[railstart] += static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
}

View File

@ -51,12 +51,8 @@ namespace solver
template <typename T>
void LE_back_subst(T & x);
PALIGNAS_VECTOROPT()
plib::parray<FT, SIZE> m_new_V;
PALIGNAS_VECTOROPT()
plib::parray2D<FT, SIZE, m_pitch_ABS> m_A;
PALIGNAS_VECTOROPT()
plib::parray<FT, SIZE> m_RHS;
};
// ----------------------------------------------------------------------------------------
@ -81,7 +77,7 @@ namespace solver
const FT f1 = -f * m_A[j][i];
for (auto &k : nzrd)
m_A[j][k] += m_A[i][k] * f1;
m_RHS[j] += m_RHS[i] * f1;
this->m_RHS[j] += this->m_RHS[i] * f1;
}
}
}
@ -93,8 +89,8 @@ namespace solver
std::size_t maxrow = i;
for (std::size_t j = i + 1; j < kN; j++)
{
//if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
if (m_A[j][i] * m_A[j][i] > m_A[maxrow][i] * m_A[maxrow][i])
if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
//if (m_A[j][i] * m_A[j][i] > m_A[maxrow][i] * m_A[maxrow][i])
maxrow = j;
}
@ -104,7 +100,7 @@ namespace solver
for (std::size_t k = 0; k < kN; k++) {
std::swap(m_A[i][k], m_A[maxrow][k]);
}
std::swap(m_RHS[i], m_RHS[maxrow]);
std::swap(this->m_RHS[i], this->m_RHS[maxrow]);
}
/* FIXME: Singular matrix? */
const FT f = plib::reciprocal(m_A[i][i]);
@ -123,7 +119,7 @@ namespace solver
// pj[k] = pj[k] + pi[k] * f1;
//for (unsigned k = i+1; k < kN; k++)
//A(j,k) += A(i,k) * f1;
m_RHS[j] += m_RHS[i] * f1;
this->m_RHS[j] += this->m_RHS[i] * f1;
}
}
}
@ -145,7 +141,7 @@ namespace solver
FT tmp = 0;
for (std::size_t k = j+1; k < kN; k++)
tmp += m_A[j][k] * x[k];
x[j] = (m_RHS[j] - tmp) / m_A[j][j];
x[j] = (this->m_RHS[j] - tmp) / m_A[j][j];
}
}
else
@ -157,7 +153,7 @@ namespace solver
const auto e = nzrd.size(); // - 1; /* exclude RHS element */
for ( std::size_t k = 0; k < e; k++)
tmp += m_A[j][nzrd[k]] * x[nzrd[k]];
x[j] = (m_RHS[j] - tmp) / m_A[j][j];
x[j] = (this->m_RHS[j] - tmp) / m_A[j][j];
}
}
}
@ -166,11 +162,13 @@ namespace solver
unsigned matrix_solver_direct_t<FT, SIZE>::solve_non_dynamic(const bool newton_raphson)
{
this->LE_solve();
this->LE_back_subst(m_new_V);
this->LE_back_subst(this->m_new_V);
const FT err = (newton_raphson ? this->delta(m_new_V) : plib::constants<FT>::zero());
this->store(m_new_V);
return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
template <typename FT, int SIZE>
@ -178,7 +176,7 @@ namespace solver
{
/* populate matrix */
this->clear_square_mat(m_A);
this->fill_matrix(m_RHS);
this->fill_matrix_and_rhs();
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);
@ -191,9 +189,7 @@ namespace solver
const std::size_t size)
: matrix_solver_ext_t<FT, SIZE>(anetlist, name, nets, params, size)
, m_pitch(m_pitch_ABS ? m_pitch_ABS : (((size + 0) + 7) / 8) * 8)
, m_new_V(size)
, m_A(size, m_pitch)
, m_RHS(size)
{
this->build_mat_ptr(m_A);
}

View File

@ -35,19 +35,19 @@ namespace solver
unsigned vsolve_non_dynamic(const bool newton_raphson) override
{
this->clear_square_mat(this->m_A);
this->fill_matrix(this->m_RHS);
this->fill_matrix_and_rhs();
std::array<FT, 1> new_V = { this->m_RHS[0] / this->m_A[0][0] };
this->m_new_V[0] = this->m_RHS[0] / this->m_A[0][0];
const FT err = (newton_raphson ? this->delta(new_V) : plib::constants<FT>::zero());
this->store(new_V);
return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
};
} // namespace solver
} // namespace netlist

View File

@ -35,7 +35,7 @@ namespace solver
unsigned vsolve_non_dynamic(const bool newton_raphson) override
{
this->clear_square_mat(this->m_A);
this->fill_matrix(this->m_RHS);
this->fill_matrix_and_rhs();
const float_type a = this->m_A[0][0];
const float_type b = this->m_A[0][1];
@ -44,12 +44,15 @@ namespace solver
const float_type v1 = (a * this->m_RHS[1] - c * this->m_RHS[0]) / (a * d - b * c);
const float_type v0 = (this->m_RHS[0] - b * v1) / a;
std::array<float_type, 2> new_V = {v0, v1};
this->m_new_V[0] = v0;
this->m_new_V[1] = v1;
this->m_stat_calculations++;
const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants<FT>::zero());
this->store(new_V);
return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
};

View File

@ -36,8 +36,6 @@ namespace solver
const analog_net_t::list_t &nets,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_ext_t<FT, SIZE>(anetlist, name, nets, params, size)
, RHS(size)
, new_V(size)
, mat(static_cast<typename mat_type::index_type>(size))
, m_proc()
{
@ -120,9 +118,6 @@ namespace solver
pstring static_compile_name();
plib::parray<FT, SIZE> RHS;
plib::parray<FT, SIZE> new_V;
mat_type mat;
plib::dynproc<void, FT * , FT * , FT * > m_proc;
@ -137,9 +132,11 @@ namespace solver
void matrix_solver_GCR_t<FT, SIZE>::generate_code(plib::putf8_fmt_writer &strm)
{
const std::size_t iN = this->size();
pstring fptype(fp_constants<FT>::name());
pstring fpsuffix(fp_constants<FT>::suffix());
for (std::size_t i = 0; i < mat.nz_num; i++)
strm("double m_A{1} = m_A[{2}];\n", i, i);
strm("{1} m_A{2} = m_A[{3}];\n", fptype, i, i);
for (std::size_t i = 0; i < iN - 1; i++)
{
@ -150,7 +147,7 @@ namespace solver
std::size_t pi = mat.diag[i];
//const FT f = 1.0 / m_A[pi++];
strm("const double f{1} = 1.0 / m_A{2};\n", i, pi);
strm("const {1} f{2} = 1.0{3} / m_A{4};\n", fptype, i, fpsuffix, pi);
pi++;
const std::size_t piie = mat.row_idx[i+1];
@ -164,7 +161,7 @@ namespace solver
pj++;
//const FT f1 = - m_A[pj++] * f;
strm("\tconst double f{1}_{2} = -f{3} * m_A{4};\n", i, j, i, pj);
strm("\tconst {1} f{2}_{3} = -f{4} * m_A{5};\n", fptype, i, j, i, pj);
pj++;
// subtract row i from j */
@ -186,7 +183,7 @@ namespace solver
strm("\tV[{1}] = RHS[{2}] / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
for (std::size_t j = iN - 1; j-- > 0;)
{
strm("\tdouble tmp{1} = 0.0;\n", j);
strm("\t{1} tmp{2} = 0.0{3};\n", fptype, j, fpsuffix);
const std::size_t e = mat.row_idx[j+1];
for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
{
@ -214,8 +211,9 @@ namespace solver
t.imbue(std::locale::classic());
plib::putf8_fmt_writer strm(&t);
pstring name = static_compile_name();
pstring fptype(fp_constants<FT>::name());
strm.writeline(plib::pfmt("extern \"C\" void {1}(double * __restrict m_A, double * __restrict RHS, double * __restrict V)\n")(name));
strm.writeline(plib::pfmt("extern \"C\" void {1}({2} * __restrict m_A, {2} * __restrict RHS, {2} * __restrict V)\n")(name, fptype));
strm.writeline("{\n");
generate_code(strm);
strm.writeline("}\n");
@ -228,28 +226,30 @@ namespace solver
{
/* populate matrix */
mat.set_scalar(plib::constants<FT>::zero());
this->fill_matrix(RHS);
this->fill_matrix_and_rhs();
/* now solve it */
if (m_proc.resolved())
{
m_proc(&mat.A[0], &RHS[0], &new_V[0]);
m_proc(&mat.A[0], &this->m_RHS[0], &this->m_new_V[0]);
}
else
{
// parallel is slow -- very slow
//mat.gaussian_elimination_parallel(RHS);
mat.gaussian_elimination(RHS);
mat.gaussian_elimination(this->m_RHS);
/* backward substitution */
mat.gaussian_back_substitution(new_V, RHS);
mat.gaussian_back_substitution(this->m_new_V, this->m_RHS);
}
this->m_stat_calculations++;
const FT err = (newton_raphson ? this->delta(new_V) : plib::constants<FT>::zero());
this->store(new_V);
return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
} // namespace solver

View File

@ -101,12 +101,10 @@ namespace solver
{
const std::size_t iN = this->size();
plib::parray<FT, SIZE> RHS(iN);
m_ops.m_mat.set_scalar(plib::constants<FT>::zero());
/* populate matrix and V for first estimate */
this->fill_matrix(RHS);
this->fill_matrix_and_rhs();
for (std::size_t k = 0; k < iN; k++)
{
@ -116,7 +114,7 @@ namespace solver
const float_type accuracy = static_cast<float_type>(this->m_params.m_accuracy);
auto iter = std::max(plib::constants<std::size_t>::one(), this->m_params.m_gs_loops());
auto gsl = m_gmres.solve(m_ops, this->m_new_V, RHS, iter, accuracy);
auto gsl = m_gmres.solve(m_ops, this->m_new_V, this->m_RHS, iter, accuracy);
this->m_iterative_total += gsl;
this->m_stat_calculations++;
@ -127,9 +125,11 @@ namespace solver
return matrix_solver_direct_t<FT, SIZE>::vsolve_non_dynamic(newton_raphson);
}
const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero());
this->store(this->m_new_V);
return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}

View File

@ -204,8 +204,6 @@ namespace solver
static constexpr const bool incremental = true;
const std::size_t iN = this->size();
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<float_type, storage_N> new_V;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<float_type, m_pitch> v;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
@ -277,11 +275,13 @@ namespace solver
m_cnt++;
this->LE_compute_x(new_V);
this->LE_compute_x(this->m_new_V);
const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants<FT>::zero());
this->store(new_V);
return (err > static_cast<FT>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
template <typename FT, int SIZE>
@ -289,7 +289,7 @@ namespace solver
{
this->clear_square_mat(this->m_A);
this->fill_matrix(this->m_RHS);
this->fill_matrix_and_rhs();
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);

View File

@ -36,8 +36,6 @@ namespace solver
, m_lp_fact(*this, "m_lp_fact", 0)
, w(size, plib::constants<FT>::zero())
, one_m_w(size, plib::constants<FT>::zero())
, RHS(size, plib::constants<FT>::zero())
//, new_V(size, 0.0)
{
}
@ -47,8 +45,6 @@ namespace solver
state_var<float_type> m_lp_fact;
std::vector<float_type> w;
std::vector<float_type> one_m_w;
std::vector<float_type> RHS;
//std::vector<float_type> new_V;
};
// ----------------------------------------------------------------------------------------
@ -74,9 +70,9 @@ namespace solver
for (std::size_t k = 0; k < iN; k++)
{
nl_fptype gtot_t = 0.0;
nl_fptype gabs_t = 0.0;
nl_fptype RHS_t = 0.0;
nl_fptype gtot_t = plib::constants<nl_fptype>::zero();
nl_fptype gabs_t = plib::constants<nl_fptype>::zero();
nl_fptype RHS_t = plib::constants<nl_fptype>::zero();
const std::size_t term_count = this->m_terms[k].count();
const nl_fptype * const gt = this->m_gtn[k];
@ -95,7 +91,7 @@ namespace solver
for (std::size_t i = this->m_terms[k].railstart(); i < term_count; i++)
RHS_t = RHS_t - go[i] * *other_cur_analog[i];
RHS[k] = static_cast<float_type>(RHS_t);
this->m_RHS[k] = static_cast<float_type>(RHS_t);
if (this->m_params.m_use_gabs)
{
@ -136,7 +132,7 @@ namespace solver
for (std::size_t i = 0; i < railstart; i++)
Idrive = Idrive - static_cast<float_type>(go[i]) * this->m_new_V[static_cast<std::size_t>(net_other[i])];
const float_type new_val = this->m_new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k];
const float_type new_val = this->m_new_V[k] * one_m_w[k] + (Idrive + this->m_RHS[k]) * w[k];
err = std::max(std::abs(new_val - this->m_new_V[k]), err);
this->m_new_V[k] = new_val;
@ -158,9 +154,11 @@ namespace solver
return matrix_solver_direct_t<FT, SIZE>::vsolve_non_dynamic(newton_raphson);
}
const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero());
this->store(this->m_new_V);
return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
} // namespace solver

View File

@ -117,7 +117,7 @@ namespace solver
const std::size_t iN = this->size();
this->clear_square_mat(this->m_A);
this->fill_matrix(this->m_RHS);
this->fill_matrix_and_rhs();
bool resched = false;
@ -210,10 +210,11 @@ namespace solver
return matrix_solver_direct_t<FT, SIZE>::solve_non_dynamic(newton_raphson);
}
const float_type err = (newton_raphson ? this->delta(this->m_new_V) : plib::constants<FT>::zero());
this->store(this->m_new_V);
return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
} // namespace solver

View File

@ -213,8 +213,6 @@ namespace solver
{
const auto iN = this->size();
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<float_type, storage_N> new_V;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
std::array<float_type, storage_N> t; // FIXME: convert to member
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init)
@ -224,12 +222,12 @@ namespace solver
{
/* complete calculation */
this->LE_invert();
this->LE_compute_x(new_V);
this->LE_compute_x(this->m_new_V);
}
else
{
/* Solve Ay = b for y */
this->LE_compute_x(new_V);
this->LE_compute_x(this->m_new_V);
/* determine changed rows */
@ -261,7 +259,7 @@ namespace solver
const unsigned r = rows[i];
FT tmp = plib::constants<FT>::zero();
for (unsigned k = 0; k < iN; k++)
tmp += VT(r,k) * new_V[k];
tmp += VT(r,k) * this->m_new_V[k];
w[i] = tmp;
}
@ -328,7 +326,7 @@ namespace solver
const unsigned row = rows[j];
tmp += Ainv(i,row) * t[j];
}
new_V[i] -= tmp;
this->m_new_V[i] -= tmp;
}
}
}
@ -340,22 +338,24 @@ namespace solver
float_type tmp = plib::constants<FT>::zero();
for (unsigned j=0; j<iN; j++)
{
tmp += A(i,j) * new_V[j];
tmp += A(i,j) * this->m_new_V[j];
}
if (std::abs(tmp-RHS(i)) > static_cast<float_type>(1e-6))
plib::perrlogger("{} failed on row {}: {} RHS: {}\n", this->name(), i, std::abs(tmp-RHS(i)), RHS(i));
}
const float_type err = (newton_raphson ? this->delta(new_V) : plib::constants<FT>::zero());
this->store(new_V);
return (err > static_cast<float_type>(this->m_params.m_accuracy)) ? 2 : 1;
bool err(false);
if (newton_raphson)
err = this->check_err();
this->store();
return (err) ? 2 : 1;
}
template <typename FT, int SIZE>
unsigned matrix_solver_w_t<FT, SIZE>::vsolve_non_dynamic(const bool newton_raphson)
{
this->clear_square_mat(this->m_A);
this->fill_matrix(this->m_RHS);
this->fill_matrix_and_rhs();
this->m_stat_calculations++;
return this->solve_non_dynamic(newton_raphson);