diff options
| author | 2016-03-27 03:15:27 +0200 | |
|---|---|---|
| committer | 2016-03-27 15:41:42 +0200 | |
| commit | 9d2f61ee92b9e1116ad4afdc51551546c729a551 (patch) | |
| tree | 4b06bd517d83c316f27e69d095460cf7a815a8d2 /src/lib/netlist/solver | |
| parent | 2e21930b27320bfdd50b536191143849d98d2815 (diff) | |
netlist:
- more code optimization
- hide matrix_solver_t implementation
- use netlist_time for time deltas
Diffstat (limited to 'src/lib/netlist/solver')
| -rw-r--r-- | src/lib/netlist/solver/nld_matrix_solver.h | 144 | ||||
| -rw-r--r-- | src/lib/netlist/solver/nld_ms_direct.h | 105 | ||||
| -rw-r--r-- | src/lib/netlist/solver/nld_ms_direct1.h | 22 | ||||
| -rw-r--r-- | src/lib/netlist/solver/nld_ms_gmres.h | 31 | ||||
| -rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 35 | ||||
| -rw-r--r-- | src/lib/netlist/solver/nld_solver.h | 130 |
6 files changed, 224 insertions, 243 deletions
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h new file mode 100644 index 00000000000..40896d431e5 --- /dev/null +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -0,0 +1,144 @@ +// license:GPL-2.0+ +// copyright-holders:Couriersud +/* + * nld_matrix_solver.h + * + */ + +#ifndef NLD_MATRIX_SOLVER_H_ +#define NLD_MATRIX_SOLVER_H_ + +#include "solver/nld_solver.h" + +NETLIB_NAMESPACE_DEVICES_START() + +class terms_t +{ + P_PREVENT_COPYING(terms_t) + + public: + ATTR_COLD terms_t() : m_railstart(0) + {} + + ATTR_COLD void clear() + { + m_term.clear(); + m_net_other.clear(); + m_gt.clear(); + m_go.clear(); + m_Idr.clear(); + m_other_curanalog.clear(); + } + + ATTR_COLD void add(terminal_t *term, int net_other, bool sorted); + + inline unsigned count() { return m_term.size(); } + + inline terminal_t **terms() { return m_term.data(); } + inline int *net_other() { return m_net_other.data(); } + inline nl_double *gt() { return m_gt.data(); } + inline nl_double *go() { return m_go.data(); } + inline nl_double *Idr() { return m_Idr.data(); } + inline nl_double **other_curanalog() { return m_other_curanalog.data(); } + + ATTR_COLD void set_pointers(); + + unsigned m_railstart; + + pvector_t<unsigned> m_nz; /* all non zero for multiplication */ + pvector_t<unsigned> m_nzrd; /* non zero right of the diagonal for elimination, includes RHS element */ + pvector_t<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */ +private: + pvector_t<terminal_t *> m_term; + pvector_t<int> m_net_other; + pvector_t<nl_double> m_go; + pvector_t<nl_double> m_gt; + pvector_t<nl_double> m_Idr; + pvector_t<nl_double *> m_other_curanalog; +}; + +class matrix_solver_t : public device_t +{ +public: + typedef pvector_t<matrix_solver_t *> list_t; + typedef core_device_t::list_t dev_list_t; + + enum eSolverType + { + GAUSSIAN_ELIMINATION, + GAUSS_SEIDEL + }; + + matrix_solver_t(const eSolverType type, const solver_parameters_t *params); + virtual ~matrix_solver_t(); + + void setup(analog_net_t::list_t &nets) { vsetup(nets); } + + netlist_time solve_base(); + + netlist_time solve(); + + inline bool is_dynamic() const { return m_dynamic_devices.size() > 0; } + inline bool is_timestep() const { return m_step_devices.size() > 0; } + + void update_forced(); + void update_after(const netlist_time after) + { + m_Q_sync.net().reschedule_in_queue(after); + } + + /* netdevice functions */ + virtual void update() override; + virtual void start() override; + virtual void reset() override; + + ATTR_COLD int get_net_idx(net_t *net); + + eSolverType type() const { return m_type; } + plog_base<NL_DEBUG> &log() { return netlist().log(); } + + virtual void log_stats(); + +protected: + + ATTR_COLD void setup_base(analog_net_t::list_t &nets); + void update_dynamic(); + + virtual void add_term(int net_idx, terminal_t *term) = 0; + virtual void vsetup(analog_net_t::list_t &nets) = 0; + virtual int vsolve_non_dynamic(const bool newton_raphson) = 0; + virtual netlist_time compute_next_timestep() = 0; + + pvector_t<analog_net_t *> m_nets; + pvector_t<analog_output_t *> m_inps; + + int m_stat_calculations; + int m_stat_newton_raphson; + int m_stat_vsolver_calls; + int m_iterative_fail; + int m_iterative_total; + + const solver_parameters_t &m_params; + + inline nl_double current_timestep() { return m_cur_ts; } +private: + + netlist_time m_last_step; + nl_double m_cur_ts; + dev_list_t m_step_devices; + dev_list_t m_dynamic_devices; + + logic_input_t m_fb_sync; + logic_output_t m_Q_sync; + + void step(const netlist_time &delta); + + void update_inputs(); + + const eSolverType m_type; +}; + + +NETLIB_NAMESPACE_DEVICES_END() + +#endif /* NLD_MS_DIRECT_H_ */ diff --git a/src/lib/netlist/solver/nld_ms_direct.h b/src/lib/netlist/solver/nld_ms_direct.h index 586b71a2bbe..5d0167f8758 100644 --- a/src/lib/netlist/solver/nld_ms_direct.h +++ b/src/lib/netlist/solver/nld_ms_direct.h @@ -39,32 +39,30 @@ public: virtual void vsetup(analog_net_t::list_t &nets) override; virtual void reset() override { matrix_solver_t::reset(); } - inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; } - - virtual int vsolve_non_dynamic(const bool newton_raphson) override; - protected: virtual void add_term(int net_idx, terminal_t *term) override; - + virtual int vsolve_non_dynamic(const bool newton_raphson) override; int solve_non_dynamic(const bool newton_raphson); + + inline const unsigned N() const { if (m_N == 0) return m_dim; else return m_N; } + void build_LE_A(); void build_LE_RHS(); void LE_solve(); - void LE_back_subst(nl_double * RESTRICT x); - /* Full LU back substitution, not used currently, in for future use */ + template <typename T> + void LE_back_subst(T * RESTRICT x); - void LE_back_subst_full(nl_double * RESTRICT x); + template <typename T> + T delta(const T * RESTRICT V); - nl_double delta(const nl_double * RESTRICT V); - void store(const nl_double * RESTRICT V); + template <typename T> + void store(const T * RESTRICT V); - /* bring the whole system to the current time - * Don't schedule a new calculation time. The recalculation has to be - * triggered by the caller after the netlist element was changed. - */ - virtual nl_double compute_next_timestep() override; + virtual netlist_time compute_next_timestep() override; + terms_t **m_terms; + terms_t *m_rails_temp; #if (NL_USE_DYNAMIC_ALLOCATION) template <typename T1, typename T2> @@ -76,13 +74,11 @@ protected: inline nl_ext_double &A(const T1 &r, const T2 &c) { return m_A[r][c]; } template <typename T1> inline nl_ext_double &RHS(const T1 &r) { return m_A[r][N()]; } - #endif ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents ATTR_ALIGN nl_double m_last_V[_storage_N]; - terms_t **m_terms; - terms_t *m_rails_temp; + private: static const unsigned m_pitch = (((_storage_N + 1) + 7) / 8) * 8; @@ -94,6 +90,7 @@ private: //ATTR_ALIGN nl_ext_double m_RHSx[_storage_N]; const unsigned m_dim; + }; // ---------------------------------------------------------------------------------------- @@ -115,7 +112,7 @@ matrix_solver_direct_t<m_N, _storage_N>::~matrix_solver_direct_t() } template <unsigned m_N, unsigned _storage_N> -nl_double matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep() +netlist_time matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep() { nl_double new_solver_timestep = m_params.m_max_timestep; @@ -152,7 +149,7 @@ nl_double matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep() } //if (new_solver_timestep > 10.0 * hn) // new_solver_timestep = 10.0 * hn; - return new_solver_timestep; + return netlist_time::from_double(new_solver_timestep); } template <unsigned m_N, unsigned _storage_N> @@ -284,9 +281,15 @@ ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::lis t->m_nz.push_back(other[i]); } } + /* Add RHS element */ + if (!t->m_nzrd.contains(N())) + t->m_nzrd.push_back(N()); + + /* and sort */ psort_list(t->m_nzrd); t->m_nz.push_back(k); // add diagonal + psort_list(t->m_nz); } @@ -437,7 +440,7 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_solve() if (f1 != NL_FCONST(0.0)) { nl_double * RESTRICT pi = &A(i,i+1); - nl_double * RESTRICT pj = &A(j,i+1); + const nl_double * RESTRICT pj = &A(j,i+1); #if 1 vec_add_mult_scalar(kN-i,pj,f1,pi); #else @@ -466,23 +469,18 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_solve() { const unsigned j = pb[jb]; const nl_double f1 = - A(j,i) * f; -#if 0 - nl_double * RESTRICT pi = &m_A[i][i+1]; - nl_double * RESTRICT pj = &m_A[j][i+1]; - vec_add_mult_scalar(kN-i-1,pi,f1,pj); -#else for (unsigned k = 0; k < e; k++) A(j,p[k]) += A(i,p[k]) * f1; -#endif - RHS(j) += RHS(i) * f1; + //RHS(j) += RHS(i) * f1; } } } } template <unsigned m_N, unsigned _storage_N> +template <typename T> void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( - nl_double * RESTRICT x) + T * RESTRICT x) { const unsigned kN = N(); @@ -491,7 +489,7 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( { for (int j = kN - 1; j >= 0; j--) { - nl_double tmp = 0; + T tmp = 0; for (unsigned k = j+1; k < kN; k++) tmp += A(j,k) * x[k]; x[j] = (RHS(j) - tmp) / A(j,j); @@ -501,10 +499,10 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( { for (int j = kN - 1; j >= 0; j--) { - nl_double tmp = 0; + T tmp = 0; const unsigned *p = m_terms[j]->m_nzrd.data(); - const unsigned e = m_terms[j]->m_nzrd.size(); + const unsigned e = m_terms[j]->m_nzrd.size() - 1; /* exclude RHS element */ for (unsigned k = 0; k < e; k++) { @@ -516,43 +514,11 @@ void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst( } } -template <unsigned m_N, unsigned _storage_N> -void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst_full( - nl_double * RESTRICT x) -{ - const unsigned kN = N(); - - /* back substitution */ - - // int ip; - // ii=-1 - - //for (int i=0; i < kN; i++) - // x[i] = m_RHS[i]; - - for (int i=0; i < kN; i++) - { - //ip=indx[i]; USE_PIVOT_SEARCH - //sum=b[ip]; - //b[ip]=b[i]; - double sum=RHS(i);//x[i]; - for (int j=0; j < i; j++) - sum -= A(i,j) * x[j]; - x[i]=sum; - } - for (int i=kN-1; i >= 0; i--) - { - double sum=x[i]; - for (int j = i+1; j < kN; j++) - sum -= A(i,j)*x[j]; - x[i] = sum / A(i,i); - } - -} template <unsigned m_N, unsigned _storage_N> -nl_double matrix_solver_direct_t<m_N, _storage_N>::delta( - const nl_double * RESTRICT V) +template <typename T> +T matrix_solver_direct_t<m_N, _storage_N>::delta( + const T * RESTRICT V) { /* FIXME: Ideally we should also include currents (RHS) here. This would * need a revaluation of the right hand side after voltages have been updated @@ -560,15 +526,16 @@ nl_double matrix_solver_direct_t<m_N, _storage_N>::delta( */ const unsigned iN = this->N(); - nl_double cerr = 0; + T cerr = 0; for (unsigned i = 0; i < iN; i++) cerr = std::max(cerr, nl_math::abs(V[i] - this->m_nets[i]->m_cur_Analog)); return cerr; } template <unsigned m_N, unsigned _storage_N> +template <typename T> void matrix_solver_direct_t<m_N, _storage_N>::store( - const nl_double * RESTRICT V) + const T * RESTRICT V) { for (unsigned i = 0, iN=N(); i < iN; i++) { diff --git a/src/lib/netlist/solver/nld_ms_direct1.h b/src/lib/netlist/solver/nld_ms_direct1.h index 909792a2787..ab19c92a4cb 100644 --- a/src/lib/netlist/solver/nld_ms_direct1.h +++ b/src/lib/netlist/solver/nld_ms_direct1.h @@ -30,25 +30,23 @@ public: inline int matrix_solver_direct1_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson) { - analog_net_t *net = m_nets[0]; this->build_LE_A(); this->build_LE_RHS(); //NL_VERBOSE_OUT(("{1} {2}\n", new_val, m_RHS[0] / m_A[0][0]); - nl_double new_val = RHS(0) / A(0,0); + nl_double new_val[1] = { RHS(0) / A(0,0) }; - nl_double e = (new_val - net->Q_Analog()); - nl_double cerr = nl_math::abs(e); - - net->m_cur_Analog = new_val; - - if (is_dynamic() && (cerr > m_params.m_accuracy)) + if (is_dynamic()) { - return 2; + nl_double err = this->delta(new_val); + store(new_val); + if (err > m_params.m_accuracy ) + return 2; + else + return 1; } - else - return 1; - + store(new_val); + return 1; } NETLIB_NAMESPACE_DEVICES_END() diff --git a/src/lib/netlist/solver/nld_ms_gmres.h b/src/lib/netlist/solver/nld_ms_gmres.h index 483decbd05d..6ff0d43f421 100644 --- a/src/lib/netlist/solver/nld_ms_gmres.h +++ b/src/lib/netlist/solver/nld_ms_gmres.h @@ -58,7 +58,7 @@ public: private: - int solve_ilu_gmres(nl_double * RESTRICT x, nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy); + int solve_ilu_gmres(nl_double * RESTRICT x, const nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy); pvector_t<int> m_term_cr[_storage_N]; @@ -157,6 +157,7 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton const nl_double * const * RESTRICT other_cur_analog = this->m_terms[k]->other_curanalog(); l_V[k] = new_V[k] = this->m_nets[k]->m_cur_Analog; + for (unsigned i = 0; i < term_count; i++) { gtot_t = gtot_t + gt[i]; @@ -180,7 +181,7 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton mat.ia[iN] = mat.nz_num; const nl_double accuracy = this->m_params.m_accuracy; -#if 1 + int mr = _storage_N; if (_storage_N > 3 ) mr = (int) sqrt(iN); @@ -188,19 +189,12 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton int iter = 4; int gsl = solve_ilu_gmres(new_V, RHS, iter, mr, accuracy); int failed = mr * iter; -#else - int failed = 6; - //int gsl = tt_ilu_cr(new_V, RHS, failed, accuracy); - int gsl = tt_gs_cr(new_V, RHS, failed, accuracy); -#endif + this->m_iterative_total += gsl; this->m_stat_calculations++; if (gsl>=failed) { - //for (int k = 0; k < iN; k++) - // this->m_nets[k]->m_cur_Analog = new_V[k]; - // Fallback to direct solver ... this->m_iterative_fail++; return matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(newton_raphson); } @@ -226,17 +220,18 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton } } -static inline void givens_mult( const nl_double c, const nl_double s, nl_double * RESTRICT g0, nl_double * RESTRICT g1 ) +template <typename T> +inline void givens_mult( const T c, const T s, T & g0, T & g1 ) { - const double tg0 = c * *g0 - s * *g1; - const double tg1 = s * *g0 + c * *g1; + const T tg0 = c * g0 - s * g1; + const T tg1 = s * g0 + c * g1; - *g0 = tg0; - *g1 = tg1; + g0 = tg0; + g1 = tg1; } template <unsigned m_N, unsigned _storage_N> -int matrix_solver_GMRES_t<m_N, _storage_N>::solve_ilu_gmres (nl_double * RESTRICT x, nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy) +int matrix_solver_GMRES_t<m_N, _storage_N>::solve_ilu_gmres (nl_double * RESTRICT x, const nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy) { /*------------------------------------------------------------------------- * The code below was inspired by code published by John Burkardt under @@ -342,7 +337,7 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::solve_ilu_gmres (nl_double * RESTRIC vec_scale(n, m_v[k1], NL_FCONST(1.0) / m_ht[k1][k]); for (unsigned j = 0; j < k; j++) - givens_mult(m_c[j], m_s[j], &m_ht[j][k], &m_ht[j+1][k]); + givens_mult(m_c[j], m_s[j], m_ht[j][k], m_ht[j+1][k]); mu = std::sqrt(std::pow(m_ht[k][k], 2) + std::pow(m_ht[k1][k], 2)); @@ -351,7 +346,7 @@ int matrix_solver_GMRES_t<m_N, _storage_N>::solve_ilu_gmres (nl_double * RESTRIC m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[k1][k]; m_ht[k1][k] = 0.0; - givens_mult(m_c[k], m_s[k], &m_g[k], &m_g[k1]); + givens_mult(m_c[k], m_s[k], m_g[k], m_g[k1]); rho = std::abs(m_g[k1]); diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index 39e4fdaacf2..5a7c8fecd40 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -31,7 +31,16 @@ #include <iostream> #include <algorithm> +//#include "nld_twoterm.h" +#include "nl_lists.h" + +#if HAS_OPENMP +#include "omp.h" +#endif + #include "nld_solver.h" +#include "nld_matrix_solver.h" + #if 1 #include "nld_ms_direct.h" #else @@ -42,12 +51,6 @@ #include "nld_ms_sor.h" #include "nld_ms_sor_mat.h" #include "nld_ms_gmres.h" -//#include "nld_twoterm.h" -#include "nl_lists.h" - -#if HAS_OPENMP -#include "omp.h" -#endif NETLIB_NAMESPACE_DEVICES_START() @@ -222,28 +225,28 @@ ATTR_COLD void matrix_solver_t::reset() ATTR_COLD void matrix_solver_t::update() { - const nl_double new_timestep = solve(); + const netlist_time new_timestep = solve(); - if (m_params.m_dynamic && is_timestep() && new_timestep > 0) - m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(new_timestep)); + if (m_params.m_dynamic && is_timestep() && new_timestep > netlist_time::zero) + m_Q_sync.net().reschedule_in_queue(new_timestep); } ATTR_COLD void matrix_solver_t::update_forced() { - ATTR_UNUSED const nl_double new_timestep = solve(); + ATTR_UNUSED const netlist_time new_timestep = solve(); if (m_params.m_dynamic && is_timestep()) m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep)); } -void matrix_solver_t::step(const netlist_time delta) +void matrix_solver_t::step(const netlist_time &delta) { const nl_double dd = delta.as_double(); for (std::size_t k=0; k < m_step_devices.size(); k++) m_step_devices[k]->step_time(dd); } -nl_double matrix_solver_t::solve_base() +netlist_time matrix_solver_t::solve_base() { m_stat_vsolver_calls++; if (is_dynamic()) @@ -273,7 +276,7 @@ nl_double matrix_solver_t::solve_base() return this->compute_next_timestep(); } -nl_double matrix_solver_t::solve() +netlist_time matrix_solver_t::solve() { const netlist_time now = netlist().time(); const netlist_time delta = now - m_last_step; @@ -281,7 +284,7 @@ nl_double matrix_solver_t::solve() // We are already up to date. Avoid oscillations. // FIXME: Make this a parameter! if (delta < netlist_time::from_nsec(1)) // 20000 - return -1.0; + return netlist_time::from_nsec(0); /* update all terminals for new time step */ m_last_step = now; @@ -289,7 +292,7 @@ nl_double matrix_solver_t::solve() step(delta); - const nl_double next_time_step = solve_base(); + const netlist_time next_time_step = solve_base(); update_inputs(); return next_time_step; @@ -427,7 +430,7 @@ NETLIB_UPDATE(solver) for (auto & solver : m_mat_solvers) if (solver->is_timestep()) // Ignore return value - ATTR_UNUSED const nl_double ts = solver->solve(); + ATTR_UNUSED const netlist_time ts = solver->solve(); #endif /* step circuit */ diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index 93d1e18be0e..6d08e0bbb73 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -48,133 +48,7 @@ struct solver_parameters_t }; -class terms_t -{ - P_PREVENT_COPYING(terms_t) - - public: - ATTR_COLD terms_t() : m_railstart(0) - {} - - ATTR_COLD void clear() - { - m_term.clear(); - m_net_other.clear(); - m_gt.clear(); - m_go.clear(); - m_Idr.clear(); - m_other_curanalog.clear(); - } - - ATTR_COLD void add(terminal_t *term, int net_other, bool sorted); - - inline unsigned count() { return m_term.size(); } - - inline terminal_t **terms() { return m_term.data(); } - inline int *net_other() { return m_net_other.data(); } - inline nl_double *gt() { return m_gt.data(); } - inline nl_double *go() { return m_go.data(); } - inline nl_double *Idr() { return m_Idr.data(); } - inline nl_double **other_curanalog() { return m_other_curanalog.data(); } - - ATTR_COLD void set_pointers(); - - unsigned m_railstart; - - pvector_t<unsigned> m_nz; /* all non zero for multiplication */ - pvector_t<unsigned> m_nzrd; /* non zero right of the diagonal for elimination */ - pvector_t<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */ -private: - pvector_t<terminal_t *> m_term; - pvector_t<int> m_net_other; - pvector_t<nl_double> m_go; - pvector_t<nl_double> m_gt; - pvector_t<nl_double> m_Idr; - pvector_t<nl_double *> m_other_curanalog; -}; - -class matrix_solver_t : public device_t -{ -public: - typedef pvector_t<matrix_solver_t *> list_t; - typedef core_device_t::list_t dev_list_t; - - enum eSolverType - { - GAUSSIAN_ELIMINATION, - GAUSS_SEIDEL - }; - - ATTR_COLD matrix_solver_t(const eSolverType type, const solver_parameters_t *params); - virtual ~matrix_solver_t(); - - void setup(analog_net_t::list_t &nets) { vsetup(nets); } - - nl_double solve_base(); - - nl_double solve(); - - inline bool is_dynamic() const { return m_dynamic_devices.size() > 0; } - inline bool is_timestep() const { return m_step_devices.size() > 0; } - - void update_forced(); - void update_after(const netlist_time after) - { - m_Q_sync.net().reschedule_in_queue(after); - } - - /* netdevice functions */ - virtual void update() override; - virtual void start() override; - virtual void reset() override; - - ATTR_COLD int get_net_idx(net_t *net); - - eSolverType type() const { return m_type; } - plog_base<NL_DEBUG> &log() { return netlist().log(); } - - virtual void log_stats(); - -protected: - - ATTR_COLD void setup_base(analog_net_t::list_t &nets); - void update_dynamic(); - - virtual void add_term(int net_idx, terminal_t *term) = 0; - virtual void vsetup(analog_net_t::list_t &nets) = 0; - virtual int vsolve_non_dynamic(const bool newton_raphson) = 0; - virtual nl_double compute_next_timestep() = 0; - - pvector_t<analog_net_t *> m_nets; - pvector_t<analog_output_t *> m_inps; - - int m_stat_calculations; - int m_stat_newton_raphson; - int m_stat_vsolver_calls; - int m_iterative_fail; - int m_iterative_total; - - const solver_parameters_t &m_params; - - inline nl_double current_timestep() { return m_cur_ts; } -private: - - netlist_time m_last_step; - nl_double m_cur_ts; - dev_list_t m_step_devices; - dev_list_t m_dynamic_devices; - - logic_input_t m_fb_sync; - logic_output_t m_Q_sync; - - void step(const netlist_time delta); - - void update_inputs(); - - const eSolverType m_type; -}; - - +class matrix_solver_t; class NETLIB_NAME(solver) : public device_t { @@ -216,7 +90,7 @@ protected: param_logic_t m_log_stats; - matrix_solver_t::list_t m_mat_solvers; + pvector_t<matrix_solver_t *> m_mat_solvers; private: solver_parameters_t m_params; |
