summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/solver/nld_solver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/solver/nld_solver.cpp')
-rw-r--r--src/lib/netlist/solver/nld_solver.cpp317
1 files changed, 205 insertions, 112 deletions
diff --git a/src/lib/netlist/solver/nld_solver.cpp b/src/lib/netlist/solver/nld_solver.cpp
index 445608a2c27..d7381cc813a 100644
--- a/src/lib/netlist/solver/nld_solver.cpp
+++ b/src/lib/netlist/solver/nld_solver.cpp
@@ -4,9 +4,10 @@
// Names
// spell-checker: words Woodbury,
-#include "nl_factory.h"
-#include "core/setup.h"
+#include "nld_solver.h"
+
#include "nl_errstr.h"
+#include "nl_factory.h"
#include "nl_setup.h" // FIXME: only needed for splitter code
#include "nld_matrix_solver.h"
#include "nld_ms_direct.h"
@@ -18,7 +19,9 @@
#include "nld_ms_sor.h"
#include "nld_ms_sor_mat.h"
#include "nld_ms_w.h"
-#include "nld_solver.h"
+
+#include "core/setup.h"
+
#include "plib/pomp.h"
#include "plib/ptimed_queue.h"
@@ -28,9 +31,27 @@
namespace netlist::devices
{
- // ----------------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
// solver
- // ----------------------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
+
+ nld_solver::nld_solver(constructor_param_t data)
+ : device_t(data)
+ , m_fb_step(*this, "FB_step", NETLIB_DELEGATE(fb_step<false>))
+ , m_Q_step(*this, "Q_step")
+ , m_params(*this, "", solver::solver_parameter_defaults::get_instance())
+ , m_queue(
+ this->state().pool(), config::max_solver_queue_size(),
+ queue_type::id_delegate(&NETLIB_NAME(solver)::get_solver_id, this),
+ queue_type::obj_delegate(&NETLIB_NAME(solver)::solver_by_id, this))
+ {
+ // internal stuff
+ state().save(*this,
+ static_cast<plib::state_manager_t::callback_t &>(m_queue),
+ this->name(), "m_queue");
+
+ connect("FB_step", "Q_step");
+ }
NETLIB_RESET(solver)
{
@@ -54,16 +75,28 @@ namespace netlist::devices
NETLIB_HANDLER(solver, fb_step)
{
const netlist_time_ext now(exec().time());
- const std::size_t nthreads = m_params.m_parallel() < 2 ? 1 : std::min(static_cast<std::size_t>(m_params.m_parallel()), plib::omp::get_max_threads());
- const netlist_time_ext sched(now + (nthreads <= 1 ? netlist_time_ext::zero() : netlist_time_ext::from_nsec(100)));
- plib::uninitialised_array<solver::matrix_solver_t *, config::max_solver_queue_size::value> tmp; //NOLINT
- plib::uninitialised_array<netlist_time, config::max_solver_queue_size::value> nt; //NOLINT
- std::size_t p=0;
+ const std::size_t nthreads = m_params.m_parallel() < 2
+ ? 1
+ : std::min(
+ static_cast<std::size_t>(
+ m_params.m_parallel()),
+ plib::omp::get_max_threads());
+ const netlist_time_ext sched(
+ now
+ + (nthreads <= 1 ? netlist_time_ext::zero()
+ : netlist_time_ext::from_nsec(100)));
+ plib::uninitialised_array<solver::matrix_solver_t *,
+ config::max_solver_queue_size::value>
+ tmp; // NOLINT
+ plib::uninitialised_array<netlist_time,
+ config::max_solver_queue_size::value>
+ nt; // NOLINT
+ std::size_t p = 0;
while (!m_queue.empty())
{
const auto t = m_queue.top().exec_time();
- auto *o = m_queue.top().object();
+ auto * o = m_queue.top().object();
if (t != now)
if (t > sched)
break;
@@ -71,14 +104,15 @@ namespace netlist::devices
m_queue.pop();
}
- // FIXME: Disabled for now since parallel processing will decrease performance
+ // FIXME: Disabled for now since parallel processing will decrease
+ // performance
// for tested applications. More testing required here
if (true || nthreads < 2)
{
if (!KEEP_STATS)
{
for (std::size_t i = 0; i < p; i++)
- nt[i] = tmp[i]->solve(now, "no-parallel");
+ nt[i] = tmp[i]->solve(now, "no-parallel");
}
else
{
@@ -102,10 +136,9 @@ namespace netlist::devices
else
{
plib::omp::set_num_threads(nthreads);
- plib::omp::for_static(static_cast<std::size_t>(0), p, [&tmp, &nt,now](std::size_t i)
- {
- nt[i] = tmp[i]->solve(now, "parallel");
- });
+ plib::omp::for_static(static_cast<std::size_t>(0), p,
+ [&tmp, &nt, now](std::size_t i)
+ { nt[i] = tmp[i]->solve(now, "parallel"); });
for (std::size_t i = 0; i < p; i++)
{
if (nt[i] != netlist_time::zero())
@@ -114,10 +147,12 @@ namespace netlist::devices
}
}
if (!m_queue.empty())
- m_Q_step.net().toggle_and_push_to_queue(static_cast<netlist_time>(m_queue.top().exec_time() - now));
+ m_Q_step.net().toggle_and_push_to_queue(
+ static_cast<netlist_time>(m_queue.top().exec_time() - now));
}
- void NETLIB_NAME(solver) :: reschedule(solver::matrix_solver_t *solv, netlist_time ts)
+ void NETLIB_NAME(solver)::reschedule(solver::matrix_solver_t *solv,
+ netlist_time ts)
{
const netlist_time_ext now(exec().time());
const netlist_time_ext sched(now + ts);
@@ -141,78 +176,101 @@ namespace netlist::devices
netlist_time_ext now(exec().time());
// force solving during start up if there are no time-step devices
// FIXME: Needs a more elegant solution
- bool force_solve = (now < netlist_time_ext::from_fp<decltype(m_params.m_max_time_step)>(2 * m_params.m_max_time_step));
+ bool force_solve = (now < netlist_time_ext::from_fp<
+ decltype(m_params.m_max_time_step)>(
+ 2 * m_params.m_max_time_step));
- std::size_t nthreads = std::min(static_cast<std::size_t>(m_params.m_parallel()), plib::omp::get_max_threads());
+ std::size_t nthreads = std::min(
+ static_cast<std::size_t>(m_params.m_parallel()),
+ plib::omp::get_max_threads());
- std::vector<solver_entry *> &solvers = (force_solve ? m_mat_solvers_all : m_mat_solvers_time_stepping);
+ std::vector<solver_entry *>
+ &solvers = (force_solve ? m_mat_solvers_all
+ : m_mat_solvers_time_stepping);
if (nthreads > 1 && solvers.size() > 1)
{
plib::omp::set_num_threads(nthreads);
- plib::omp::for_static(static_cast<std::size_t>(0), solvers.size(), [&solvers, now](std::size_t i)
- {
- [[maybe_unused]] const netlist_time ts = solvers[i]->ptr->solve(now);
+ plib::omp::for_static(
+ static_cast<std::size_t>(0), solvers.size(),
+ [&solvers, now](std::size_t i) {
+ [[maybe_unused]] const netlist_time ts = solvers[i]
+ ->ptr->solve(
+ now);
});
}
else
- for (auto & solver : solvers)
+ for (auto &solver : solvers)
{
- [[maybe_unused]] const netlist_time ts = solver->ptr->solve(now);
+ [[maybe_unused]] const netlist_time ts = solver->ptr->solve(
+ now);
}
- for (auto & solver : solvers)
+ for (auto &solver : solvers)
solver->ptr->update_inputs();
// step circuit
if (!m_Q_step.net().is_queued())
{
- m_Q_step.net().toggle_and_push_to_queue(netlist_time::from_fp(m_params.m_max_time_step));
+ m_Q_step.net().toggle_and_push_to_queue(
+ netlist_time::from_fp(m_params.m_max_time_step));
}
}
#endif
// FIXME: should be created in device space
template <class C, class A>
- NETLIB_NAME(solver)::solver_ptr create_it(A &arena, NETLIB_NAME(solver) &main_solver, pstring name,
- NETLIB_NAME(solver)::net_list_t &nets,
- const solver::solver_parameters_t *params, std::size_t size)
+ NETLIB_NAME(solver)::solver_ptr
+ create_it(A &arena, NETLIB_NAME(solver) &main_solver, pstring name,
+ NETLIB_NAME(solver)::net_list_t & nets,
+ const solver::solver_parameters_t *params, std::size_t size)
{
- return plib::make_unique<C>(arena, main_solver, name, nets, params, size);
+ return plib::make_unique<C>(arena, main_solver, name, nets, params,
+ size);
}
template <typename FT, int SIZE>
- NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solver(std::size_t size,
- const pstring &solver_name, const solver::solver_parameters_t *params,
- NETLIB_NAME(solver)::net_list_t &nets)
+ NETLIB_NAME(solver)::solver_ptr NETLIB_NAME(solver)::create_solver(
+ std::size_t size, const pstring &solver_name,
+ const solver::solver_parameters_t *params,
+ NETLIB_NAME(solver)::net_list_t & nets)
{
switch (params->m_method())
{
case solver::matrix_type_e::MAT_CR:
- return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
case solver::matrix_type_e::MAT:
- return create_it<solver::matrix_solver_direct_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_direct_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
case solver::matrix_type_e::GMRES:
- return create_it<solver::matrix_solver_GMRES_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_GMRES_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
#if (NL_USE_ACADEMIC_SOLVERS)
case solver::matrix_type_e::SOR:
- return create_it<solver::matrix_solver_SOR_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_SOR_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
case solver::matrix_type_e::SOR_MAT:
- return create_it<solver::matrix_solver_SOR_mat_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_SOR_mat_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
case solver::matrix_type_e::SM:
// Sherman-Morrison Formula
- return create_it<solver::matrix_solver_sm_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_sm_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
case solver::matrix_type_e::W:
// Woodbury Formula
- return create_it<solver::matrix_solver_w_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ return create_it<solver::matrix_solver_w_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
#else
- //case solver::matrix_type_e::GMRES:
+ // case solver::matrix_type_e::GMRES:
case solver::matrix_type_e::SOR:
case solver::matrix_type_e::SOR_MAT:
case solver::matrix_type_e::SM:
case solver::matrix_type_e::W:
- state().log().warning(MW_SOLVER_METHOD_NOT_SUPPORTED(params->m_method().name(), "MAT_CR"));
- return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(state().pool(), *this, solver_name, nets, params, size);
+ state().log().warning(MW_SOLVER_METHOD_NOT_SUPPORTED(
+ params->m_method().name(), "MAT_CR"));
+ return create_it<solver::matrix_solver_GCR_t<FT, SIZE>>(
+ state().pool(), *this, solver_name, nets, params, size);
#endif
}
return solver_ptr();
@@ -228,47 +286,49 @@ namespace netlist::devices
{
#if !defined(__EMSCRIPTEN__)
case 1:
- return plib::make_unique<solver::matrix_solver_direct1_t<FT>>(state().pool(), *this, sname, nets, params);
+ return plib::make_unique<solver::matrix_solver_direct1_t<FT>>(
+ state().pool(), *this, sname, nets, params);
case 2:
- return plib::make_unique<solver::matrix_solver_direct2_t<FT>>(state().pool(), *this, sname, nets, params);
- case 3:
- return create_solver<FT, 3>(3, sname, params, nets);
- case 4:
- return create_solver<FT, 4>(4, sname, params, nets);
- case 5:
- return create_solver<FT, 5>(5, sname, params, nets);
- case 6:
- return create_solver<FT, 6>(6, sname, params, nets);
- case 7:
- return create_solver<FT, 7>(7, sname, params, nets);
- case 8:
- return create_solver<FT, 8>(8, sname, params, nets);
+ return plib::make_unique<solver::matrix_solver_direct2_t<FT>>(
+ state().pool(), *this, sname, nets, params);
+ case 3: return create_solver<FT, 3>(3, sname, params, nets);
+ case 4: return create_solver<FT, 4>(4, sname, params, nets);
+ case 5: return create_solver<FT, 5>(5, sname, params, nets);
+ case 6: return create_solver<FT, 6>(6, sname, params, nets);
+ case 7: return create_solver<FT, 7>(7, sname, params, nets);
+ case 8: return create_solver<FT, 8>(8, sname, params, nets);
#endif
default:
log().info(MI_NO_SPECIFIC_SOLVER(net_count));
if (net_count <= 16)
{
- return create_solver<FT, -16>(net_count, sname, params, nets);
+ return create_solver<FT, -16>(net_count, sname, params,
+ nets);
}
if (net_count <= 32)
{
- return create_solver<FT, -32>(net_count, sname, params, nets);
+ return create_solver<FT, -32>(net_count, sname, params,
+ nets);
}
if (net_count <= 64)
{
- return create_solver<FT, -64>(net_count, sname, params, nets);
+ return create_solver<FT, -64>(net_count, sname, params,
+ nets);
}
if (net_count <= 128)
{
- return create_solver<FT, -128>(net_count, sname, params, nets);
+ return create_solver<FT, -128>(net_count, sname, params,
+ nets);
}
if (net_count <= 256)
{
- return create_solver<FT, -256>(net_count, sname, params, nets);
+ return create_solver<FT, -256>(net_count, sname, params,
+ nets);
}
if (net_count <= 512)
{
- return create_solver<FT, -512>(net_count, sname, params, nets);
+ return create_solver<FT, -512>(net_count, sname, params,
+ nets);
}
return create_solver<FT, 0>(net_count, sname, params, nets);
}
@@ -278,18 +338,21 @@ namespace netlist::devices
{
void run(netlist_state_t &nl_state)
{
- for (auto & net : nl_state.nets())
+ for (auto &net : nl_state.nets())
{
nl_state.log().verbose("processing {1}", net->name());
if (!net->is_rail_net() && !net->core_terms_empty())
{
nl_state.log().verbose(" ==> not a rail net");
// Must be an analog net
- auto &n = dynamic_cast<analog_net_t &>(*net);
- if (!already_processed(n))
+ auto n = plib::dynamic_downcast<analog_net_t *>(net.get());
+ nl_assert_always(bool(n),
+ "Unable to cast to analog_net_t &");
+ if (!already_processed(*(*n)))
{
- groupspre.emplace_back(NETLIB_NAME(solver)::net_list_t());
- process_net(nl_state, n);
+ groupspre.emplace_back(
+ NETLIB_NAME(solver)::net_list_t());
+ process_net(nl_state, *(*n));
}
}
}
@@ -301,14 +364,13 @@ namespace netlist::devices
std::vector<NETLIB_NAME(solver)::net_list_t> groups;
private:
-
bool already_processed(const analog_net_t &n) const
{
// no need to process rail nets - these are known variables
if (n.is_rail_net())
return true;
// if it's already processed - no need to continue
- for (const auto & grp : groups)
+ for (const auto &grp : groups)
if (plib::container::contains(grp, &n))
return true;
return false;
@@ -323,12 +385,13 @@ namespace netlist::devices
// In this case we need to merge this group into the current group
if (groupspre.size() > 1)
{
- for (std::size_t i = 0; i<groupspre.size() - 1; i++)
+ for (std::size_t i = 0; i < groupspre.size() - 1; i++)
if (plib::container::contains(groupspre[i], &n))
{
// copy all nets
- for (auto & cn : groupspre[i])
- if (!plib::container::contains(groupspre.back(), cn))
+ for (auto &cn : groupspre[i])
+ if (!plib::container::contains(groupspre.back(),
+ cn))
groupspre.back().push_back(cn);
// clear
groupspre[i].clear();
@@ -336,7 +399,8 @@ namespace netlist::devices
}
}
// if it's already processed - no need to continue
- if (!groupspre.empty() && plib::container::contains(groupspre.back(), &n))
+ if (!groupspre.empty()
+ && plib::container::contains(groupspre.back(), &n))
return true;
return false;
}
@@ -353,20 +417,26 @@ namespace netlist::devices
// add the net
groupspre.back().push_back(&n);
// process all terminals connected to this net
- for (detail::core_terminal_t * term : terminals)
+ for (detail::core_terminal_t *term : terminals)
{
- nl_state.log().verbose("Term {} {}", term->name(), static_cast<int>(term->type()));
+ nl_state.log().verbose("Term {} {}", term->name(),
+ static_cast<int>(term->type()));
// only process analog terminals
if (term->is_type(detail::terminal_type::TERMINAL))
{
- auto &pt = dynamic_cast<terminal_t &>(*term);
+ auto pt = plib::dynamic_downcast<terminal_t *>(term);
+ nl_assert_always(bool(pt),
+ "Error casting *term to terminal_t &");
// check the connected terminal
- const auto *const connected_terminals = nl_state.setup().get_connected_terminals(pt);
+ const auto *const connected_terminals
+ = nl_state.setup().get_connected_terminals(*(*pt));
// NOLINTNEXTLINE proposal does not work for VS
- for (auto ct = connected_terminals->begin(); *ct != nullptr; ct++)
+ for (auto ct = connected_terminals->begin();
+ *ct != nullptr; ct++)
{
analog_net_t &connected_net = (*ct)->net();
- nl_state.log().verbose(" Connected net {}", connected_net.name());
+ nl_state.log().verbose(" Connected net {}",
+ connected_net.name());
if (!check_if_processed_and_join(connected_net))
process_net(nl_state, connected_net);
}
@@ -386,40 +456,48 @@ namespace netlist::devices
net_splitter splitter;
splitter.run(state());
- log().verbose("Found {1} net groups in {2} nets\n", splitter.groups.size(), state().nets().size());
+ log().verbose("Found {1} net groups in {2} nets\n",
+ splitter.groups.size(), state().nets().size());
int num_errors = 0;
log().verbose("checking net consistency ...");
for (const auto &grp : splitter.groups)
{
- int rail_terminals = 0;
+ int rail_terminals = 0;
pstring nets_in_grp;
for (const auto &n : grp)
{
nets_in_grp += (n->name() + " ");
if (!n->is_analog())
{
- state().log().error(ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n->name()));
+ state().log().error(
+ ME_SOLVER_CONSISTENCY_NOT_ANALOG_NET(n->name()));
num_errors++;
}
if (n->is_rail_net())
{
- state().log().error(ME_SOLVER_CONSISTENCY_RAIL_NET(n->name()));
+ state().log().error(
+ ME_SOLVER_CONSISTENCY_RAIL_NET(n->name()));
num_errors++;
}
- for (detail::core_terminal_t * t : n->core_terms_copy())
+ for (detail::core_terminal_t *t : n->core_terms_copy())
{
if (!t->has_net())
{
- state().log().error(ME_SOLVER_TERMINAL_NO_NET(t->name()));
+ state().log().error(
+ ME_SOLVER_TERMINAL_NO_NET(t->name()));
num_errors++;
}
else
{
- auto *other_terminal = dynamic_cast<terminal_t *>(t);
- if (other_terminal != nullptr)
- if (state().setup().get_connected_terminal(*other_terminal)->net().is_rail_net())
+ if (auto other_terminal = plib::dynamic_downcast<
+ terminal_t *>(t))
+ if (state()
+ .setup()
+ .get_connected_terminal(*(*other_terminal))
+ ->net()
+ .is_rail_net())
rail_terminals++;
}
}
@@ -433,43 +511,56 @@ namespace netlist::devices
if (num_errors > 0)
throw nl_exception(MF_SOLVER_CONSISTENCY_ERRORS(num_errors));
-
// setup the solvers
- for (auto & grp : splitter.groups)
+ for (auto &grp : splitter.groups)
{
- solver_ptr ms;
- pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
- params_uptr params = plib::make_unique<solver::solver_parameters_t>(state().pool(), *this, sname + ".", m_params);
+ solver_ptr ms;
+ pstring sname = plib::pfmt("Solver_{1}")(m_mat_solvers.size());
+ params_uptr params = plib::make_unique<solver::solver_parameters_t>(
+ state().pool(), *this, sname + ".", m_params);
switch (params->m_fp_type())
{
case solver::matrix_fp_type_e::FLOAT:
if (!config::use_float_matrix::value)
- log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name());
- ms = create_solvers<std::conditional_t<config::use_float_matrix::value, float, double>>(sname, params.get(), grp);
+ log().info("FPTYPE {1} not supported. Using DOUBLE",
+ params->m_fp_type().name());
+ ms = create_solvers<std::conditional_t<
+ config::use_float_matrix::value, float, double>>(
+ sname, params.get(), grp);
break;
case solver::matrix_fp_type_e::DOUBLE:
ms = create_solvers<double>(sname, params.get(), grp);
break;
case solver::matrix_fp_type_e::LONGDOUBLE:
if (!config::use_long_double_matrix::value)
- log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name());
- ms = create_solvers<std::conditional_t<config::use_long_double_matrix::value, long double, double>>(sname, params.get(), grp);
+ log().info("FPTYPE {1} not supported. Using DOUBLE",
+ params->m_fp_type().name());
+ ms = create_solvers<std::conditional_t<
+ config::use_long_double_matrix::value, long double,
+ double>>(sname, params.get(), grp);
break;
case solver::matrix_fp_type_e::FLOATQ128:
#if (NL_USE_FLOAT128)
ms = create_solvers<FLOAT128>(sname, params.get(), grp);
#else
- log().info("FPTYPE {1} not supported. Using DOUBLE", params->m_fp_type().name());
+ log().info("FPTYPE {1} not supported. Using DOUBLE",
+ params->m_fp_type().name());
ms = create_solvers<double>(sname, params.get(), grp);
#endif
break;
}
+ state().register_device(
+ ms->name(),
+ device_arena::owned_ptr<core_device_t>(ms.get(), false));
+
log().verbose("Solver {1}", ms->name());
log().verbose(" ==> {1} nets", grp.size());
- log().verbose(" has {1} dynamic elements", ms->dynamic_device_count());
- log().verbose(" has {1} time step elements", ms->time_step_device_count());
+ log().verbose(" has {1} dynamic elements",
+ ms->dynamic_device_count());
+ log().verbose(" has {1} time step elements",
+ ms->time_step_device_count());
for (auto &n : grp)
{
log().verbose("Net {1}", n->name());
@@ -482,35 +573,37 @@ namespace netlist::devices
m_mat_params.push_back(std::move(params));
m_mat_solvers.push_back(std::move(ms));
}
-
}
- solver::static_compile_container NETLIB_NAME(solver)::create_solver_code(solver::static_compile_target target)
+ solver::static_compile_container NETLIB_NAME(solver)::create_solver_code(
+ solver::static_compile_target target)
{
solver::static_compile_container mp;
- for (auto & s : m_mat_solvers)
+ for (auto &s : m_mat_solvers)
{
auto r = s->create_solver_code(target);
- if (!r.first.empty()) // ignore solvers not supporting static compile
+ if (!r.first.empty()) // ignore solvers not supporting static
+ // compile
mp.push_back(r);
}
return mp;
}
- std::size_t NETLIB_NAME(solver)::get_solver_id(const solver::matrix_solver_t *net) const
+ std::size_t NETLIB_NAME(solver)::get_solver_id(
+ const solver::matrix_solver_t *net) const
{
- for (std::size_t i=0; i < m_mat_solvers.size(); i++)
+ for (std::size_t i = 0; i < m_mat_solvers.size(); i++)
if (m_mat_solvers[i].get() == net)
return i;
return std::numeric_limits<std::size_t>::max();
}
- solver::matrix_solver_t * NETLIB_NAME(solver)::solver_by_id(std::size_t id) const
+ solver::matrix_solver_t *NETLIB_NAME(solver)::solver_by_id(
+ std::size_t id) const
{
return m_mat_solvers[id].get();
}
-
NETLIB_DEVICE_IMPL(solver, "SOLVER", "FREQ")
} // namespace netlist::devices