diff options
Diffstat (limited to 'src/lib/netlist/solver/nld_solver.cpp')
-rw-r--r-- | src/lib/netlist/solver/nld_solver.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp index ed011ff254d..5dd0af53313 100644 --- a/src/lib/netlist/solver/nld_solver.cpp +++ b/src/lib/netlist/solver/nld_solver.cpp @@ -108,6 +108,11 @@ ATTR_COLD matrix_solver_t::matrix_solver_t(const eSolverType type, const solver_ ATTR_COLD matrix_solver_t::~matrix_solver_t() { m_inps.clear_and_free(); + for (unsigned k = 0; k < m_terms.size(); k++) + { + pfree(m_terms[k]); + } + } ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets) @@ -115,9 +120,14 @@ ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets) log().debug("New solver setup\n"); m_nets.clear(); + m_terms.clear(); for (auto & net : nets) + { m_nets.push_back(net); + m_terms.push_back(palloc(terms_t)); + m_rails_temp.push_back(palloc(terms_t)); + } for (std::size_t k = 0; k < nets.size(); k++) { @@ -168,6 +178,9 @@ ATTR_COLD void matrix_solver_t::setup_base(analog_net_t::list_t &nets) if (net_proxy_output == NULL) { + //net_proxy_output = palloc(analog_output_t(*this, + // this->name() + "." + pfmt("m{1}")(m_inps.size()))); + net_proxy_output = palloc(analog_output_t); net_proxy_output->init_object(*this, this->name() + "." + pfmt("m{1}")(m_inps.size())); m_inps.push_back(net_proxy_output); @@ -308,6 +321,70 @@ ATTR_COLD int matrix_solver_t::get_net_idx(net_t *net) return -1; } +ATTR_COLD void matrix_solver_t::add_term(int k, terminal_t *term) +{ + if (term->m_otherterm->net().isRailNet()) + { + m_rails_temp[k]->add(term, -1, false); + } + else + { + int ot = get_net_idx(&term->m_otherterm->net()); + if (ot>=0) + { + m_terms[k]->add(term, ot, true); + } + /* Should this be allowed ? */ + else // if (ot<0) + { + m_rails_temp[k]->add(term, ot, true); + log().fatal("found term with missing othernet {1}\n", term->name()); + } + } +} + +netlist_time matrix_solver_t::compute_next_timestep() +{ + nl_double new_solver_timestep = m_params.m_max_timestep; + + if (m_params.m_dynamic) + { + /* + * FIXME: We should extend the logic to use either all nets or + * only output nets. + */ + for (unsigned k = 0, iN=m_terms.size(); k < iN; k++) + { + analog_net_t *n = m_nets[k]; + + const nl_double DD_n = (n->Q_Analog() - m_terms[k]->m_last_V); + const nl_double hn = current_timestep(); + + nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1); + nl_double new_net_timestep; + + n->m_h_n_m_1 = hn; + n->m_DD_n_m_1 = DD_n; + if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero + new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2)); + else + new_net_timestep = m_params.m_max_timestep; + + if (new_net_timestep < new_solver_timestep) + new_solver_timestep = new_net_timestep; + + m_terms[k]->m_last_V = n->Q_Analog(); + } + if (new_solver_timestep < m_params.m_min_timestep) + new_solver_timestep = m_params.m_min_timestep; + } + //if (new_solver_timestep > 10.0 * hn) + // new_solver_timestep = 10.0 * hn; + return netlist_time::from_double(new_solver_timestep); +} + + + void matrix_solver_t::log_stats() { if (this->m_stat_calculations != 0 && this->m_stat_vsolver_calls && this->m_params.m_log_stats) |