summaryrefslogtreecommitdiffstats
path: root/src/lib/netlist/solver/nld_matrix_solver.h
blob: 40896d431e5d2fcc63eb9b8cdeb13df57bd92975 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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_ */