trunk/src/emu/netlist/analog/nld_solver.c
| r30700 | r30701 | |
| 23 | 23 | // ---------------------------------------------------------------------------------------- |
| 24 | 24 | |
| 25 | 25 | ATTR_COLD netlist_matrix_solver_t::netlist_matrix_solver_t() |
| 26 | | : m_owner(NULL) |
| 27 | | , m_calculations(0) |
| 26 | : m_calculations(0) |
| 28 | 27 | { |
| 29 | 28 | } |
| 30 | 29 | |
| r30700 | r30701 | |
| 34 | 33 | delete m_inps[i]; |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | | ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &aowner) |
| 36 | ATTR_COLD void netlist_matrix_solver_t::setup(netlist_analog_net_t::list_t &nets) |
| 38 | 37 | { |
| 39 | | m_owner = &aowner; |
| 40 | | |
| 41 | 38 | NL_VERBOSE_OUT(("New solver setup\n")); |
| 42 | 39 | |
| 43 | 40 | m_nets.resize(nets.count()); |
| r30700 | r30701 | |
| 111 | 108 | } |
| 112 | 109 | break; |
| 113 | 110 | default: |
| 114 | | owner().netlist().error("unhandled element found\n"); |
| 111 | netlist().error("unhandled element found\n"); |
| 115 | 112 | break; |
| 116 | 113 | } |
| 117 | 114 | } |
| r30700 | r30701 | |
| 255 | 252 | ATTR_HOT double netlist_matrix_solver_t::solve() |
| 256 | 253 | { |
| 257 | 254 | |
| 258 | | netlist_time now = owner().netlist().time(); |
| 255 | netlist_time now = netlist().time(); |
| 259 | 256 | netlist_time delta = now - m_last_step; |
| 260 | 257 | |
| 261 | 258 | // We are already up to date. Avoid oscillations. |
| r30700 | r30701 | |
| 275 | 272 | do |
| 276 | 273 | { |
| 277 | 274 | update_dynamic(); |
| 278 | | while ((this_resched = vsolve_non_dynamic()) > m_params.m_gs_loops) |
| 279 | | owner().netlist().warning("Dynamic Solve iterations exceeded .. Consider increasing RESCHED_LOOPS"); |
| 275 | // Gauss-Seidel will revert to Gaussian elemination if steps exceeded. |
| 276 | this_resched = vsolve_non_dynamic(); |
| 280 | 277 | newton_loops++; |
| 281 | 278 | } while (this_resched > 1 && newton_loops < m_params.m_nr_loops); |
| 282 | 279 | |
| 283 | 280 | // reschedule .... |
| 284 | 281 | if (this_resched > 1 && !m_Q_sync.net().is_queued()) |
| 285 | 282 | { |
| 286 | | owner().netlist().warning("NEWTON_LOOPS exceeded ... reschedule"); |
| 283 | netlist().warning("NEWTON_LOOPS exceeded ... reschedule"); |
| 287 | 284 | m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay); |
| 288 | 285 | return 1.0; |
| 289 | 286 | } |
| 290 | 287 | } |
| 291 | 288 | else |
| 292 | 289 | { |
| 293 | | while (vsolve_non_dynamic() > m_params.m_gs_loops) |
| 294 | | owner().netlist().warning("Non-Dynamic Solve iterations exceeded .. Consider increasing RESCHED_LOOPS"); |
| 290 | vsolve_non_dynamic(); |
| 295 | 291 | } |
| 296 | 292 | const double next_time_step = compute_next_timestep(delta.as_double()); |
| 297 | 293 | update_inputs(); |
| r30700 | r30701 | |
| 331 | 327 | } |
| 332 | 328 | |
| 333 | 329 | template <int m_N, int _storage_N> |
| 334 | | ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &owner) |
| 330 | ATTR_COLD void netlist_matrix_solver_direct_t<m_N, _storage_N>::vsetup(netlist_analog_net_t::list_t &nets) |
| 335 | 331 | { |
| 336 | 332 | m_dim = nets.count(); |
| 337 | | netlist_matrix_solver_t::setup(nets, owner); |
| 333 | netlist_matrix_solver_t::setup(nets); |
| 338 | 334 | |
| 339 | 335 | m_terms.clear(); |
| 340 | 336 | m_rail_start = 0; |
| r30700 | r30701 | |
| 1019 | 1015 | |
| 1020 | 1016 | register_sub(*ms, pstring::sprintf("Solver %d",m_mat_solvers.count())); |
| 1021 | 1017 | |
| 1022 | | ms->vsetup(groups[i], *this); |
| 1018 | ms->vsetup(groups[i]); |
| 1023 | 1019 | |
| 1024 | 1020 | m_mat_solvers.add(ms); |
| 1025 | 1021 | |
trunk/src/emu/netlist/analog/nld_solver.h
| r30700 | r30701 | |
| 46 | 46 | ATTR_COLD netlist_matrix_solver_t(); |
| 47 | 47 | ATTR_COLD virtual ~netlist_matrix_solver_t(); |
| 48 | 48 | |
| 49 | | ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets, |
| 50 | | NETLIB_NAME(solver) &owner) = 0; |
| 49 | ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets) = 0; |
| 51 | 50 | |
| 52 | 51 | ATTR_HOT double solve(); |
| 53 | 52 | |
| 54 | 53 | ATTR_HOT inline bool is_dynamic() { return m_dynamic.count() > 0; } |
| 55 | 54 | ATTR_HOT inline bool is_timestep() { return m_steps.count() > 0; } |
| 56 | 55 | |
| 57 | | ATTR_HOT inline const NETLIB_NAME(solver) &owner() const; |
| 58 | | |
| 59 | 56 | ATTR_HOT void update_forced(); |
| 60 | 57 | |
| 61 | 58 | /* netdevice functions */ |
| r30700 | r30701 | |
| 95 | 92 | netlist_terminal_t::list_t m_rails; |
| 96 | 93 | }; |
| 97 | 94 | |
| 98 | | ATTR_COLD void setup(netlist_analog_net_t::list_t &nets, |
| 99 | | NETLIB_NAME(solver) &owner); |
| 95 | ATTR_COLD void setup(netlist_analog_net_t::list_t &nets); |
| 100 | 96 | |
| 101 | | NETLIB_NAME(solver) *m_owner; |
| 102 | | |
| 103 | 97 | // return true if a reschedule is needed ... |
| 104 | 98 | ATTR_HOT virtual int vsolve_non_dynamic() = 0; |
| 105 | 99 | |
| r30700 | r30701 | |
| 143 | 137 | |
| 144 | 138 | virtual ~netlist_matrix_solver_direct_t() {} |
| 145 | 139 | |
| 146 | | ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets, NETLIB_NAME(solver) &owner); |
| 140 | ATTR_COLD virtual void vsetup(netlist_analog_net_t::list_t &nets); |
| 147 | 141 | ATTR_COLD virtual void reset() { netlist_matrix_solver_t::reset(); } |
| 148 | 142 | |
| 149 | 143 | ATTR_HOT inline const int N() const { if (m_N == 0) return m_dim; else return m_N; } |
| r30700 | r30701 | |
| 254 | 248 | netlist_solver_parameters_t m_params; |
| 255 | 249 | ); |
| 256 | 250 | |
| 257 | | ATTR_HOT inline const NETLIB_NAME(solver) &netlist_matrix_solver_t::owner() const |
| 258 | | { |
| 259 | | return *m_owner; |
| 260 | | } |
| 261 | 251 | |
| 262 | | |
| 263 | 252 | #endif /* NLD_SOLVER_H_ */ |