summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/solver/nld_matrix_solver.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/solver/nld_matrix_solver.h')
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h659
1 files changed, 374 insertions, 285 deletions
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 29017add8a9..c0b792fd597 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -1,375 +1,464 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * nld_matrix_solver.h
- *
- */
#ifndef NLD_MATRIX_SOLVER_H_
#define NLD_MATRIX_SOLVER_H_
-#include "netlist/nl_base.h"
-#include "netlist/nl_errstr.h"
+// Names
+// spell-checker: words Raphson, Seidel
+
+///
+/// \file nld_matrix_solver.h
+///
+
+#include "nl_errstr.h"
+#include "nltypes.h"
+
+#include "../core/analog.h"
+#include "../core/device.h"
+#include "../core/device_macros.h"
+#include "../core/param.h"
+
#include "plib/palloc.h"
+#include "plib/penum.h"
#include "plib/pmatrix2d.h"
+#include "plib/pmatrix_cr.h"
+#include "plib/pmempool.h"
#include "plib/putil.h"
#include "plib/vector_ops.h"
-#include <cmath>
+#include <numeric>
-namespace netlist
-{
-namespace devices
+// FIXME: remove again
+
+#define PFDEBUG(x)
+
+namespace netlist::solver
{
- /* FIXME: these should become proper devices */
- struct solver_parameters_t
+ enum static_compile_target
{
- bool m_pivot;
- nl_double m_accuracy;
- nl_double m_dynamic_lte;
- nl_double m_min_timestep;
- nl_double m_max_timestep;
- nl_double m_gs_sor;
- bool m_dynamic_ts;
- std::size_t m_gs_loops;
- std::size_t m_nr_loops;
- netlist_time m_nr_recalc_delay;
- bool m_use_gabs;
- bool m_use_linear_prediction;
+ CXX_EXTERNAL_C,
+ CXX_STATIC
};
-
- class terms_for_net_t : plib::nocopyassignmove
+ // clang-format off
+
+ PENUM(matrix_sort_type_e,
+ NOSORT,
+ ASCENDING,
+ DESCENDING,
+ PREFER_IDENTITY_TOP_LEFT,
+ PREFER_BAND_MATRIX
+ )
+
+ PENUM(matrix_type_e,
+ SOR_MAT,
+ MAT_CR,
+ MAT,
+ SM,
+ W,
+ SOR,
+ GMRES
+ )
+
+ PENUM(matrix_fp_type_e,
+ FLOAT
+ , DOUBLE
+ , LONGDOUBLE
+ , FLOATQ128
+ )
+
+ // clang-format on
+
+ using arena_type = plib::mempool_arena<plib::aligned_arena<>, 1024>;
+ using static_compile_container = std::vector<std::pair<pstring, pstring>>;
+
+ struct solver_parameter_defaults
{
- public:
- terms_for_net_t();
-
- void clear();
-
- void add(terminal_t *term, int net_other, bool sorted);
-
- std::size_t count() const { return m_terms.size(); }
-
- terminal_t **terms() { return m_terms.data(); }
+ static constexpr nl_fptype m_freq() { return nlconst::magic(48000.0); }
- std::size_t m_railstart;
+ // iteration parameters
+ static constexpr nl_fptype m_gs_sor() { return nlconst::magic(1.059); }
+ static constexpr matrix_type_e m_method()
+ {
+ return matrix_type_e::MAT_CR;
+ }
+ static constexpr matrix_fp_type_e m_fp_type()
+ {
+ return matrix_fp_type_e::DOUBLE;
+ }
+ static constexpr nl_fptype m_reltol() { return nlconst::magic(1e-3); }
+ static constexpr nl_fptype m_vntol() { return nlconst::magic(1e-7); }
+ static constexpr nl_fptype m_accuracy() { return nlconst::magic(1e-7); }
+ static constexpr std::size_t m_nr_loops() { return 250; }
+ static constexpr std::size_t m_gs_loops() { return 50; }
+
+ // general parameters
+ static constexpr nl_fptype m_gmin() { return nlconst::magic(1e-9); }
+ static constexpr bool m_pivot() { return false; }
+ static constexpr nl_fptype m_nr_recalc_delay()
+ {
+ return netlist_time::quantum().as_fp<nl_fptype>();
+ }
+ static constexpr int m_parallel() { return 0; }
- std::vector<unsigned> m_nz; /* all non zero for multiplication */
- std::vector<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */
- std::vector<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
+ static constexpr nl_fptype m_min_ts_ts()
+ {
+ return nlconst::magic(1e-9);
+ }
+ // automatic time step
+ static constexpr bool m_dynamic_ts() { return false; }
+ static constexpr nl_fptype m_dynamic_lte()
+ {
+ return nlconst::magic(1e-5);
+ }
+ static constexpr nl_fptype m_dynamic_min_ts()
+ {
+ return nlconst::magic(1e-6);
+ }
- /* state */
- nl_double m_last_V;
- nl_double m_DD_n_m_1;
- nl_double m_h_n_m_1;
+ // matrix sorting
+ static constexpr matrix_sort_type_e m_sort_type()
+ {
+ return matrix_sort_type_e::PREFER_IDENTITY_TOP_LEFT;
+ }
- std::vector<int> m_connected_net_idx;
- private:
- std::vector<terminal_t *> m_terms;
+ // special
+ static constexpr bool m_use_gabs() { return true; }
+ static solver_parameter_defaults &get_instance()
+ {
+ static solver_parameter_defaults s;
+ return s;
+ }
};
- class proxied_analog_output_t : public analog_output_t
+ struct solver_parameters_t
{
- public:
+ template <typename D>
+ solver_parameters_t(device_t &parent, const pstring &prefix,
+ D &defaults)
+ : m_freq(parent, prefix + "FREQ", defaults.m_freq())
+
+ // iteration parameters
+ , m_gs_sor(parent, prefix + "SOR_FACTOR", defaults.m_gs_sor())
+ , m_method(parent, prefix + "METHOD", defaults.m_method())
+ , m_fp_type(parent, prefix + "FPTYPE", defaults.m_fp_type())
+ , m_reltol(parent, prefix + "RELTOL",
+ defaults.m_reltol()) //!< SPICE RELTOL parameter
+ , m_vntol(parent, prefix + "VNTOL", defaults.m_vntol()) //!< SPICE VNTOL
+ //!< parameter
+ , m_accuracy(parent, prefix + "ACCURACY",
+ defaults.m_accuracy()) //!< Iterative solver accuracy
+ , m_nr_loops(parent, prefix + "NR_LOOPS",
+ defaults.m_nr_loops()) //!< Maximum number of
+ //!< Newton-Raphson loops
+ , m_gs_loops(parent, prefix + "GS_LOOPS",
+ defaults.m_gs_loops()) //!< Maximum number of Gauss-Seidel
+ //!< loops
+
+ // general parameters
+ , m_gmin(parent, prefix + "GMIN", defaults.m_gmin())
+ , m_pivot(parent, prefix + "PIVOT", defaults.m_pivot()) //!< use
+ //!< pivoting on
+ //!< supported
+ //!< solvers
+ , m_nr_recalc_delay(parent, prefix + "NR_RECALC_DELAY",
+ defaults.m_nr_recalc_delay()) //!< Delay to next
+ //!< solve attempt if
+ //!< nr loops exceeded
+ , m_parallel(parent, prefix + "PARALLEL", defaults.m_parallel())
+ , m_min_ts_ts(parent, prefix + "MIN_TS_TS",
+ defaults.m_min_ts_ts()) //!< The minimum time step for
+ //!< solvers with time stepping
+ //!< devices.
+
+ // automatic time step
+ , m_dynamic_ts(parent, prefix + "DYNAMIC_TS",
+ defaults.m_dynamic_ts()) //!< Use dynamic time stepping
+ , m_dynamic_lte(parent, prefix + "DYNAMIC_LTE",
+ defaults.m_dynamic_lte()) //!< dynamic time stepping
+ //!< slope
+ , m_dynamic_min_ts(parent, prefix + "DYNAMIC_MIN_TIMESTEP",
+ defaults.m_dynamic_min_ts()) //!< smallest time step
+ //!< allowed
+
+ // matrix sorting
+ , m_sort_type(parent, prefix + "SORT_TYPE", defaults.m_sort_type())
+
+ // special
+ , m_use_gabs(parent, prefix + "USE_GABS", defaults.m_use_gabs())
+ , m_min_time_step(m_dynamic_min_ts())
+ {
+ m_max_time_step = netlist_time::from_fp(plib::reciprocal(m_freq()))
+ .as_fp<decltype(m_max_time_step)>();
- proxied_analog_output_t(core_device_t &dev, const pstring &aname, analog_net_t *pnet)
- : analog_output_t(dev, aname)
- , m_proxied_net(pnet)
- { }
+ if (m_dynamic_ts)
+ {
+ m_max_time_step *= 1; // NL_FCONST(1000.0);
+ }
+ else
+ {
+ m_min_time_step = m_max_time_step;
+ }
+ }
- analog_net_t *proxied_net() const { return m_proxied_net;}
- private:
- analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
+ param_fp_t m_freq;
+ 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_fp_t m_nr_recalc_delay;
+ param_int_t m_parallel;
+ param_fp_t m_min_ts_ts;
+ param_logic_t m_dynamic_ts;
+ param_fp_t m_dynamic_lte;
+ param_fp_t m_dynamic_min_ts;
+ param_enum_t<matrix_sort_type_e> m_sort_type;
+
+ param_logic_t m_use_gabs;
+
+ nl_fptype m_min_time_step;
+ nl_fptype m_max_time_step;
};
- class matrix_solver_t : public device_t
+ class terms_for_net_t
{
public:
- using list_t = std::vector<matrix_solver_t *>;
+ terms_for_net_t(arena_type &arena, analog_net_t *net = nullptr);
- enum eSortType
- {
- NOSORT,
- ASCENDING,
- DESCENDING,
- PREFER_IDENTITY_TOP_LEFT,
- PREFER_BAND_MATRIX
- };
-
- void setup(analog_net_t::list_t &nets)
- {
- vsetup(nets);
- }
-
- void solve_base();
+ void clear();
- /* after every call to solve, update inputs must be called.
- * this can be done as well as a batch to ease parallel processing.
- */
- const netlist_time solve(netlist_time now);
- void update_inputs();
+ void add_terminal(terminal_t *term, int net_other, bool sorted);
- bool has_dynamic_devices() const { return m_dynamic_devices.size() > 0; }
- bool has_timestep_devices() const { return m_step_devices.size() > 0; }
+ std::size_t count() const noexcept { return m_terms.size(); }
- void update_forced();
- void update_after(const netlist_time after)
- {
- m_Q_sync.net().toggle_and_push_to_queue(after);
- }
+ std::size_t rail_start() const noexcept { return m_rail_start; }
- /* netdevice functions */
- NETLIB_UPDATEI();
- NETLIB_RESETI();
+ terminal_t **terms() noexcept { return m_terms.data(); }
- public:
- int get_net_idx(detail::net_t *net);
- std::pair<int, int> get_left_right_of_diag(std::size_t row, std::size_t diag);
- double get_weight_around_diag(std::size_t row, std::size_t diag);
+ nl_fptype getV() const noexcept { return m_net->Q_Analog(); }
- virtual void log_stats();
+ void setV(nl_fptype v) noexcept { m_net->set_Q_Analog(v); }
- virtual std::pair<pstring, pstring> create_solver_code()
+ bool is_net(const analog_net_t *net) const noexcept
{
- return std::pair<pstring, pstring>("", plib::pfmt("/* solver doesn't support static compile */\n\n"));
+ return net == m_net;
}
- /* return number of floating point operations for solve */
- std::size_t ops() { return m_ops; }
+ void set_rail_start(std::size_t val) noexcept { m_rail_start = val; }
- protected:
+ PALIGNAS_VECTOROPT()
+
+ plib::arena_vector<arena_type, unsigned> m_nz; //!< all non zero for
+ //!< multiplication
+ plib::arena_vector<arena_type, unsigned> m_nzrd; //!< non zero right of
+ //!< the diagonal for
+ //!< elimination, may
+ //!< include RHS
+ //!< element
+ plib::arena_vector<arena_type, unsigned> m_nzbd; //!< non zero below of
+ //!< the diagonal for
+ //!< elimination
- matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
- eSortType sort, const solver_parameters_t *params);
+ plib::arena_vector<arena_type, int> m_connected_net_idx;
- void sort_terms(eSortType sort);
+ private:
+ plib::arena_vector<arena_type, terminal_t *> m_terms;
+ analog_net_t *m_net;
+ std::size_t m_rail_start;
+ };
- void setup_base(analog_net_t::list_t &nets);
- void update_dynamic();
+ class proxied_analog_output_t : public analog_output_t
+ {
+ public:
+ proxied_analog_output_t(core_device_t &dev, const pstring &aname,
+ analog_net_t *pnet)
+ : analog_output_t(dev, aname)
+ , m_proxied_net(pnet)
+ {
+ }
- virtual void vsetup(analog_net_t::list_t &nets) = 0;
- virtual unsigned vsolve_non_dynamic(const bool newton_raphson) = 0;
+ analog_net_t *proxied_net() const { return m_proxied_net; }
- netlist_time compute_next_timestep(const double cur_ts);
- /* virtual */ void add_term(std::size_t net_idx, terminal_t *term);
+ private:
+ analog_net_t *m_proxied_net; // only for proxy nets in analog input
+ // logic
+ };
- template <typename T>
- void store(const T & V);
+ class matrix_solver_t : public device_t
+ {
+ public:
+ using list_t = std::vector<matrix_solver_t *>;
+ using fptype = nl_fptype;
+ using net_list_t = std::vector<analog_net_t *>;
- template <typename T>
- auto delta(const T & V) -> typename std::decay<decltype(V[0])>::type;
+ // after every call to solve, update inputs must be called.
+ // this can be done as well as a batch to ease parallel processing.
- template <typename T>
- void build_LE_A(T &child);
- template <typename T>
- void build_LE_RHS(T &child);
+ netlist_time solve(netlist_time_ext now, const char *source);
+ void update_inputs();
- void set_pointers()
+ std::size_t dynamic_device_count() const noexcept
{
- const std::size_t iN = this->m_nets.size();
+ return m_dynamic_funcs.size();
+ }
+ std::size_t time_step_device_count() const noexcept
+ {
+ return m_step_funcs.size();
+ }
- std::size_t max_count = 0;
- std::size_t max_rail = 0;
- for (std::size_t k = 0; k < iN; k++)
- {
- max_count = std::max(max_count, m_terms[k]->count());
- max_rail = std::max(max_rail, m_terms[k]->m_railstart);
- }
+ /// \brief reschedule solver execution
+ ///
+ /// Calls reschedule on main solver
+ ///
+ void reschedule(netlist_time ts);
+
+ /// \brief Immediately solve system at current time
+ ///
+ /// This should only be called from update and update_param events.
+ /// It's purpose is to bring voltage values to the current time step.
+ /// This will be called BEFORE updating object properties.
+ void solve_now()
+ {
+ // this should only occur outside of execution and thus
+ // using time should be safe.
- m_mat_ptr.resize(iN, max_rail+1);
- m_gtn.resize(iN, max_count);
- m_gonn.resize(iN, max_count);
- m_Idrn.resize(iN, max_count);
- m_connected_net_Vn.resize(iN, max_count);
+ [[maybe_unused]] const netlist_time new_time_step = solve(
+ exec().time(), "solve_now");
- for (std::size_t k = 0; k < iN; k++)
- {
- auto count = m_terms[k]->count();
+ update_inputs();
- for (std::size_t i = 0; i < count; i++)
- {
- m_terms[k]->terms()[i]->set_ptrs(&m_gtn[k][i], &m_gonn[k][i], &m_Idrn[k][i]);
- m_connected_net_Vn[k][i] = m_terms[k]->terms()[i]->connected_terminal()->net().Q_Analog_state_ptr();
- }
+ if (time_step_device_count() > 0)
+ {
+ this->reschedule(netlist_time::from_fp(
+ m_params.m_dynamic_ts ? m_params.m_min_time_step
+ : m_params.m_max_time_step));
}
}
- template <typename AP, typename FT>
- void fill_matrix(std::size_t N, AP &tcr, FT &RHS)
+ template <typename F>
+ void change_state(F f)
{
- for (std::size_t k = 0; k < N; k++)
+ // We only need to update the net first if this is a time stepping
+ // net
+ if (time_step_device_count() > 0)
{
- auto *net = m_terms[k].get();
- auto **tcr_r = &(tcr[k][0]);
-
- const std::size_t term_count = net->count();
- const std::size_t railstart = net->m_railstart;
- const auto &go = m_gonn[k];
- const auto &gt = m_gtn[k];
- const auto &Idr = m_Idrn[k];
- const auto &cnV = m_connected_net_Vn[k];
-
- for (std::size_t i = 0; i < railstart; i++)
- *tcr_r[i] += go[i];
-
- typename FT::value_type gtot_t = 0.0;
- typename FT::value_type RHS_t = 0.0;
-
- for (std::size_t i = 0; i < term_count; i++)
- {
- gtot_t += gt[i];
- RHS_t += Idr[i];
- }
- // FIXME: Code above is faster than vec_sum - Check this
- #if 0
- auto gtot_t = plib::vec_sum<FT>(term_count, m_gt);
- auto RHS_t = plib::vec_sum<FT>(term_count, m_Idr);
- #endif
-
- for (std::size_t i = railstart; i < term_count; i++)
- {
- RHS_t += (/*m_Idr[i]*/ (- go[i]) * *cnV[i]);
- }
-
- RHS[k] = RHS_t;
- // update diagonal element ...
- *tcr_r[railstart] += gtot_t; //mat.A[mat.diag[k]] += gtot_t;
+ [[maybe_unused]] const netlist_time new_time_step = solve(
+ exec().time(), "change_state");
+ update_inputs();
}
-
+ f();
+ if (time_step_device_count() > 0)
+ {
+ PFDEBUG(printf("here2\n");)
+ this->reschedule(netlist_time::from_fp(m_params.m_min_ts_ts()));
+ }
+ else
+ this->reschedule(netlist_time::quantum());
}
- template <typename T>
- using aligned_alloc = plib::aligned_allocator<T, PALIGN_VECTOROPT>;
+ NETLIB_RESETI();
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_gonn;
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_gtn;
- plib::pmatrix2d<nl_double, aligned_alloc<nl_double>> m_Idrn;
- plib::pmatrix2d<nl_double *, aligned_alloc<nl_double *>> m_mat_ptr;
- plib::pmatrix2d<nl_double *, aligned_alloc<nl_double *>> m_connected_net_Vn;
+ virtual void log_stats();
- plib::pmatrix2d<nl_double> m_test;
+ virtual std::pair<pstring, pstring> create_solver_code(
+ [[maybe_unused]] solver::static_compile_target target)
+ {
+ return {"",
+ plib::pfmt("// solver doesn't support static compile\n\n")};
+ }
- std::vector<plib::unique_ptr<terms_for_net_t>> m_terms;
- std::vector<analog_net_t *> m_nets;
- std::vector<pool_owned_ptr<proxied_analog_output_t>> m_inps;
+ // return number of floating point operations for solve
+ constexpr std::size_t ops() const { return m_ops; }
- std::vector<plib::unique_ptr<terms_for_net_t>> m_rails_temp;
+ protected:
+ matrix_solver_t(devices::nld_solver &main_solver, const pstring &name,
+ const net_list_t &nets,
+ const solver_parameters_t *params);
+
+ virtual void upstream_solve_non_dynamic() = 0;
+ virtual netlist_time
+ compute_next_time_step(fptype cur_ts, fptype min_ts, fptype max_ts)
+ = 0;
+ virtual bool check_err() const = 0;
+ virtual void store() = 0;
+ virtual void backup() = 0;
+ virtual void restore() = 0;
+
+ std::size_t max_rail_start() const noexcept
+ {
+ std::size_t max_rail = 0;
+ for (const auto &term : m_terms)
+ max_rail = std::max(max_rail, term.rail_start());
+ return max_rail;
+ }
const solver_parameters_t &m_params;
+ arena_type m_arena;
- state_var<int> m_stat_calculations;
- state_var<int> m_stat_newton_raphson;
- state_var<int> m_stat_vsolver_calls;
- state_var<int> m_iterative_fail;
- state_var<int> m_iterative_total;
-
- private:
+ plib::pmatrix2d_vrl<arena_type, fptype> m_gonn;
+ plib::pmatrix2d_vrl<arena_type, fptype> m_gtn;
+ plib::pmatrix2d_vrl<arena_type, fptype> m_Idrn;
+ plib::pmatrix2d_vrl<arena_type, fptype *> m_connected_net_Vn;
- state_var<netlist_time> m_last_step;
- std::vector<core_device_t *> m_step_devices;
- std::vector<core_device_t *> m_dynamic_devices;
+ state_var<std::size_t> m_iterative_fail;
+ state_var<std::size_t> m_iterative_total;
- logic_input_t m_fb_sync;
- logic_output_t m_Q_sync;
+ std::vector<terms_for_net_t> m_terms; // setup only
- /* calculate matrix */
- void setup_matrix();
-
- void step(const netlist_time &delta);
-
- std::size_t m_ops;
- const eSortType m_sort;
- };
-
- template <typename T>
- auto matrix_solver_t::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();
- typename std::decay<decltype(V[0])>::type cerr = 0;
- for (std::size_t i = 0; i < iN; i++)
- cerr = std::max(cerr, std::abs(V[i] - this->m_nets[i]->Q_Analog()));
- return cerr;
- }
-
- template <typename T>
- void matrix_solver_t::store(const T & V)
- {
- const std::size_t iN = this->m_terms.size();
- for (std::size_t i = 0; i < iN; i++)
- this->m_nets[i]->set_Q_Analog(V[i]);
- }
+ private:
+ // base setup - called from constructor
+ void setup_base(setup_t &setup, const net_list_t &nets) noexcept(false);
- template <typename T>
- void matrix_solver_t::build_LE_A(T &child)
- {
- using float_type = typename T::float_type;
- static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
+ bool solve_nr_base();
+ netlist_time newton_loops_exceeded(netlist_time delta);
- const std::size_t iN = child.size();
- for (std::size_t k = 0; k < iN; k++)
- {
- terms_for_net_t *terms = m_terms[k].get();
- float_type * Ak = &child.A(k, 0ul);
+ void sort_terms(matrix_sort_type_e sort);
- for (std::size_t i=0; i < iN; i++)
- Ak[i] = 0.0;
+ void update_dynamic() noexcept;
+ void step(detail::time_step_type ts_type, netlist_time delta) noexcept;
- const std::size_t terms_count = terms->count();
- const std::size_t railstart = terms->m_railstart;
- const float_type * const gt = m_gtn[k];
+ int get_net_idx(const analog_net_t *net) const noexcept;
+ std::pair<int, int>
+ get_left_right_of_diagonal(std::size_t irow, std::size_t idiag);
+ fptype get_weight_around_diagonal(std::size_t row, std::size_t diag);
- {
- float_type akk = 0.0;
- for (std::size_t i = 0; i < terms_count; i++)
- akk += gt[i];
-
- Ak[k] = akk;
- }
+ void add_term(std::size_t net_idx, terminal_t *term) noexcept(false);
- const float_type * const go = m_gonn[k];
- int * net_other = terms->m_connected_net_idx.data();
+ // calculate matrix
+ void setup_matrix();
- for (std::size_t i = 0; i < railstart; i++)
- Ak[net_other[i]] += go[i];
- }
- }
+ void set_pointers();
- template <typename T>
- void matrix_solver_t::build_LE_RHS(T &child)
- {
- static_assert(std::is_base_of<matrix_solver_t, T>::value, "T must derive from matrix_solver_t");
- using float_type = typename T::float_type;
+ analog_net_t *get_connected_net(terminal_t *term);
- const std::size_t iN = child.size();
- for (std::size_t k = 0; k < iN; k++)
- {
- float_type rhsk_a = 0.0;
- float_type rhsk_b = 0.0;
+ devices::nld_solver &m_main_solver;
- const std::size_t terms_count = m_terms[k]->count();
- const float_type * const go = m_gonn[k];
- const float_type * const Idr = m_Idrn[k];
- const float_type * const * other_cur_analog = m_connected_net_Vn[k];
+ state_var<std::size_t> m_stat_calculations;
+ state_var<std::size_t> m_stat_newton_raphson;
+ state_var<std::size_t> m_stat_newton_raphson_fail;
+ state_var<std::size_t> m_stat_vsolver_calls;
- for (std::size_t i = 0; i < terms_count; i++)
- rhsk_a = rhsk_a + Idr[i];
+ state_var<netlist_time_ext> m_last_step;
+ plib::arena_vector<arena_type, nl_delegate_ts> m_step_funcs;
+ plib::arena_vector<arena_type, nl_delegate_dyn> m_dynamic_funcs;
+ plib::arena_vector<arena_type,
+ device_arena::unique_ptr<proxied_analog_output_t>>
+ m_inputs;
- for (std::size_t i = m_terms[k]->m_railstart; i < terms_count; i++)
- //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
- rhsk_b = rhsk_b - go[i] * *other_cur_analog[i];
+ std::size_t m_ops;
- child.RHS(k) = rhsk_a + rhsk_b;
- }
- }
+ std::vector<terms_for_net_t> m_rails_temp; // setup only
+ };
-} //namespace devices
-} // namespace netlist
+} // namespace netlist::solver
-#endif /* NLD_MS_DIRECT_H_ */
+#endif // NLD_MS_DIRECT_H_