1use num::{Complex, Float, Zero};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::ops::Index;
8
9use crate::circuit::{Ckt, NodeRef};
10use crate::comps::{Component, ComponentSolver};
11use crate::defs;
12use crate::sparse21::{Eindex, Matrix};
13use crate::{sperror, SpNum, SpResult};
14
15#[derive(Debug)]
23pub(crate) struct Stamps<NumT> {
24 pub(crate) g: Vec<(Option<Eindex>, NumT)>,
25 pub(crate) b: Vec<(Option<VarIndex>, NumT)>,
26}
27impl<NumT: SpNum> Stamps<NumT> {
28 pub fn new() -> Stamps<NumT> {
29 Stamps { g: vec![], b: vec![] }
30 }
31}
32
33#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
34pub(crate) enum VarKind {
35 V = 0,
36 I,
37 Q,
38}
39
40#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
41pub struct VarIndex(pub usize);
42
43#[derive(Debug, Deserialize, Serialize)]
44pub(crate) struct Variables<NumT> {
45 kinds: Vec<VarKind>,
46 values: Vec<NumT>,
47 names: Vec<String>,
48}
49impl<NumT: SpNum> Variables<NumT> {
50 pub fn new() -> Self {
51 Variables {
52 kinds: vec![],
53 values: vec![],
54 names: vec![],
55 }
56 }
57 fn from<OtherT>(other: Variables<OtherT>) -> Self {
60 Variables {
61 kinds: other.kinds,
62 names: other.names,
63 values: vec![NumT::zero(); other.values.len()],
64 }
65 }
66 pub fn add(&mut self, name: String, kind: VarKind) -> VarIndex {
68 self.kinds.push(kind);
70 self.names.push(name);
71 self.values.push(NumT::zero());
72 return VarIndex(self.kinds.len() - 1);
73 }
74 pub fn addv(&mut self, name: String) -> VarIndex {
76 self.add(name, VarKind::V)
77 }
78 pub fn addi(&mut self, name: String) -> VarIndex {
80 self.add(name, VarKind::I)
81 }
82 pub fn find<S: Into<String>>(&self, name: S) -> Option<VarIndex> {
84 let n = name.into().clone();
85 match self.names.iter().position(|x| *x == n) {
86 Some(i) => Some(VarIndex(i)),
87 None => None,
88 }
89 }
90 pub fn find_or_create(&mut self, node: NodeRef) -> Option<VarIndex> {
93 match node {
94 NodeRef::Gnd => None,
95 NodeRef::Name(name) => {
96 match self.names.iter().cloned().position(|x| x == name) {
98 Some(i) => Some(VarIndex(i)),
99 None => Some(self.add(name.clone(), VarKind::V)),
100 }
101 }
102 NodeRef::Num(num) => {
103 let name = num.to_string();
104 match self.names.iter().cloned().position(|x| x == name) {
106 Some(i) => Some(VarIndex(i)),
107 None => Some(self.add(name.clone(), VarKind::V)),
108 }
109 }
110 }
111 }
112 pub fn get(&self, i: Option<VarIndex>) -> NumT {
115 match i {
116 None => NumT::zero(),
117 Some(ii) => self.values[ii.0],
118 }
119 }
120 pub fn len(&self) -> usize {
121 self.kinds.len()
122 }
123}
124
125#[allow(dead_code)] struct Iteration<NumT: SpNum> {
129 n: usize,
130 x: Vec<NumT>,
131 dx: Vec<NumT>,
132 vtol: Vec<bool>,
133 itol: Vec<bool>,
134}
135
136pub(crate) struct Solver<'a, NumT: SpNum> {
140 pub(crate) comps: Vec<ComponentSolver<'a>>,
141 pub(crate) vars: Variables<NumT>,
142 pub(crate) mat: Matrix<NumT>,
143 pub(crate) rhs: Vec<NumT>,
144 pub(crate) history: Vec<Vec<NumT>>,
145 pub(crate) defs: defs::Defs,
146 pub(crate) opts: Options,
147}
148
149impl Solver<'_, f64> {
152 fn update(&mut self, an: &AnalysisInfo) {
154 for comp in self.comps.iter_mut() {
155 let updates = comp.load(&self.vars, an, &self.opts);
156 for upd in updates.g.iter() {
158 if let (Some(ei), val) = *upd {
159 self.mat.update(ei, val);
160 }
161 }
162 for upd in updates.b.iter() {
163 if let (Some(ei), val) = *upd {
164 self.rhs[ei.0] += val;
165 }
166 }
167 }
168 }
169 fn solve(&mut self, an: &AnalysisInfo) -> SpResult<Vec<f64>> {
170 self.history = vec![]; let mut dx = vec![0.0; self.vars.len()];
172
173 for _k in 0..100 {
174 self.history.push(self.vars.values.clone());
177 self.mat.reset();
179 self.rhs = vec![0.0; self.vars.len()];
180
181 self.update(an);
183
184 let res: Vec<f64> = self.mat.res(&self.vars.values, &self.rhs)?;
186
187 if self.converged(&dx, &res) {
189 for c in self.comps.iter_mut() {
191 c.commit();
192 }
193 return Ok(self.vars.values.clone()); }
195 dx = self.mat.solve(res)?;
197 let max_step = 1000e-3;
198 let max_abs = dx.iter().fold(0.0, |s, v| if v.abs() > s { v.abs() } else { s });
199 if max_abs > max_step {
200 for r in 0..dx.len() {
201 dx[r] = dx[r] * max_step / max_abs;
202 }
203 }
204 for r in 0..self.vars.len() {
206 self.vars.values[r] += dx[r];
207 }
208 }
209 return Err(sperror("Convergence Failed"));
210 }
211}
212
213impl<'a> Solver<'a, Complex<f64>> {
216 fn from(re: Solver<'a, f64>) -> Self {
219 let mut op = Solver::<'a, Complex<f64>> {
220 comps: re.comps,
221 vars: Variables::<Complex<f64>>::from(re.vars),
222 mat: Matrix::new(),
223 rhs: vec![],
224 history: vec![],
225 defs: re.defs,
226 opts: re.opts,
227 };
228
229 for comp in op.comps.iter_mut() {
231 comp.create_matrix_elems(&mut op.mat);
232 }
233 return op;
234 }
235
236 fn update(&mut self, an: &AnalysisInfo) {
238 for comp in self.comps.iter_mut() {
239 let updates = comp.load_ac(&self.vars, an, &self.opts);
240 for upd in updates.g.iter() {
242 if let (Some(ei), val) = *upd {
243 self.mat.update(ei, val);
244 }
245 }
246 for upd in updates.b.iter() {
247 if let (Some(ei), val) = *upd {
248 self.rhs[ei.0] += val;
249 }
250 }
251 }
252 }
253 fn solve(&mut self, an: &AnalysisInfo) -> SpResult<Vec<Complex<f64>>> {
254 self.history = vec![]; let mut dx = vec![Complex::zero(); self.vars.len()];
256 let mut iters: Vec<Iteration<Complex<f64>>> = vec![];
257
258 for _k in 0..20 {
259 self.history.push(self.vars.values.clone());
262 self.mat.reset();
264 self.rhs = vec![Complex::zero(); self.vars.len()];
265
266 self.update(an);
268
269 let res: Vec<Complex<f64>> = self.mat.res(&self.vars.values, &self.rhs)?;
271 let vtol: Vec<bool> = dx.iter().map(|&v| v.norm() < 1e-3).collect();
272 let itol: Vec<bool> = res.iter().map(|&v| v.norm() < 1e-9).collect();
273 if vtol.iter().all(|v| *v) && itol.iter().all(|v| *v) {
275 for c in self.comps.iter_mut() {
277 c.commit();
278 }
279 return Ok(self.vars.values.clone());
280 }
281 dx = self.mat.solve(res)?;
283 let max_step = 1.0;
284 let max_abs = dx.iter().fold(0.0, |s, v| if v.norm() > s { v.norm() } else { s });
285 if max_abs > max_step {
286 for r in 0..dx.len() {
287 dx[r] = dx[r] * max_step / max_abs;
288 }
289 }
290 for r in 0..self.vars.len() {
292 self.vars.values[r] += dx[r];
293 }
294 iters.push(Iteration {
295 n: _k,
296 x: self.vars.values.clone(),
297 dx: dx.clone(),
298 vtol: vtol,
299 itol: itol,
300 });
301 }
302 return Err(sperror("Convergence Failed"));
303 }
304}
305
306impl<'a, NumT: SpNum> Solver<'a, NumT> {
307 pub(crate) fn new(ckt: Ckt, opts: Options) -> Solver<'a, NumT> {
309 use crate::elab::{elaborate, Elaborator};
311 let e = elaborate(ckt, opts);
312 let Elaborator {
313 defs, mut comps, vars, opts, ..
314 } = e;
315 let mut mat = Matrix::new();
317 for comp in comps.iter_mut() {
318 comp.create_matrix_elems(&mut mat);
319 }
320 Solver {
322 comps,
323 vars,
324 mat,
325 rhs: Vec::new(),
326 history: Vec::new(),
327 defs,
328 opts,
329 }
330 }
331 fn converged(&self, dx: &Vec<NumT>, res: &Vec<NumT>) -> bool {
332 for e in dx.iter() {
334 if e.absv() > self.opts.reltol {
335 return false;
336 }
337 }
338 for e in res.iter() {
340 if e.absv() > self.opts.iabstol {
341 return false;
342 }
343 }
344 return true;
345 }
346}
347
348#[derive(Debug)]
350pub struct OpResult {
351 pub names: Vec<String>,
352 pub values: Vec<f64>,
353 pub map: HashMap<String, f64>,
354}
355impl OpResult {
356 fn from(vars: Variables<f64>) -> Self {
358 let mut map: HashMap<String, f64> = HashMap::new();
359 for i in 0..vars.names.len() {
360 map.insert(vars.names[i].clone(), vars.values[i]);
361 }
362 let Variables { names, values, .. } = vars;
363 OpResult { names, values, map }
364 }
365 pub(crate) fn get<S: Into<String>>(&self, signame: S) -> SpResult<f64> {
367 match self.map.get(&signame.into()) {
368 Some(v) => Ok(v.clone()),
369 None => Err(sperror("Signal Not Found")),
370 }
371 }
372}
373impl Index<usize> for OpResult {
376 type Output = f64;
377 fn index(&self, t: usize) -> &f64 {
378 &self.values[t]
379 }
380}
381
382pub fn dcop(ckt: Ckt, opts: Option<Options>) -> SpResult<OpResult> {
384 let o = if let Some(o) = opts { o } else { Options::default() };
385 let mut s = Solver::<f64>::new(ckt, o);
386 let _r = s.solve(&AnalysisInfo::OP)?;
387 return Ok(OpResult::from(s.vars));
388}
389pub(crate) enum AnalysisInfo<'a> {
390 OP,
391 TRAN(&'a TranOptions, &'a TranState),
392 AC(&'a AcOptions, &'a AcState),
393}
394
395pub(crate) enum NumericalIntegration {
396 BE,
397 TRAP,
398}
399
400impl Default for NumericalIntegration {
401 fn default() -> NumericalIntegration {
402 NumericalIntegration::BE
403 }
404}
405
406#[derive(Default)]
411pub(crate) struct TranState {
412 pub(crate) t: f64,
413 pub(crate) dt: f64,
414 pub(crate) vic: Vec<usize>,
415 pub(crate) ric: Vec<usize>,
416 pub(crate) ni: NumericalIntegration,
417}
418impl TranState {
419 pub fn integrate(&self, dq: f64, dq_dv: f64, vguess: f64, _ip: f64) -> (f64, f64, f64) {
421 let dt = self.dt;
422 match self.ni {
423 NumericalIntegration::BE => {
424 let g = dq_dv / dt;
425 let i = dq / dt;
426 let rhs = i - g * vguess;
427 (g, i, rhs)
428 }
429 NumericalIntegration::TRAP => {
430 panic!("Trapezoidal Integration is Disabled!");
431 }
436 }
437 }
438 pub fn integq(&self, dq: f64, dq_dv: f64, vguess: f64, _ip: f64) -> ChargeInteg {
439 let (g, i, rhs) = self.integrate(dq, dq_dv, vguess, _ip);
440 ChargeInteg { g, i, rhs }
441 }
442}
443#[derive(Default, Clone)]
445pub(crate) struct ChargeInteg {
446 pub(crate) g: f64,
447 pub(crate) i: f64,
448 pub(crate) rhs: f64,
449}
450#[derive(Debug)]
452pub struct TranOptions {
453 pub tstep: f64,
454 pub tstop: f64,
455 pub ic: Vec<(NodeRef, f64)>,
456}
457impl TranOptions {
458 pub fn decode(bytes_: &[u8]) -> SpResult<Self> {
459 use prost::Message;
461 use std::io::Cursor;
462
463 let proto = proto::TranOptions::decode(&mut Cursor::new(bytes_))?;
465 Ok(Self::from(proto))
467 }
468}
469impl From<proto::TranOptions> for TranOptions {
470 fn from(i: proto::TranOptions) -> Self {
471 use super::circuit::n;
472 let mut ic: Vec<(NodeRef, f64)> = vec![];
473 for (name, val) in &i.ic {
474 ic.push((n(name), val.clone()));
475 }
476 Self {
477 tstep: i.tstep,
478 tstop: i.tstop,
479 ic,
480 }
481 }
482}
483impl Default for TranOptions {
484 fn default() -> TranOptions {
485 Self::from(proto::TranOptions::default())
486 }
487}
488
489pub(crate) struct Tran<'a> {
490 solver: Solver<'a, f64>,
491 state: TranState,
492 pub(crate) opts: TranOptions,
493}
494
495impl<'a> Tran<'a> {
496 pub fn new(ckt: Ckt, opts: Options, args: TranOptions) -> Tran<'a> {
497 let solver = Solver::new(ckt, opts);
498 let ics = args.ic.clone();
499 let mut t = Tran {
500 solver,
501 opts: args,
502 state: TranState::default(),
503 };
504 for (node, val) in &ics {
505 t.ic(node.clone(), *val);
506 }
507 t
508 }
509 pub fn ic(&mut self, n: NodeRef, val: f64) {
511 use crate::comps::{Resistor, Vsrc};
512
513 let fnode = self.solver.vars.add(format!(".{}.vic", n.to_string()), VarKind::V);
515 let ivar = self.solver.vars.add(format!(".{}.iic", n.to_string()), VarKind::I);
516
517 let mut r = Resistor::new(1.0, Some(fnode), self.solver.vars.find_or_create(n)); r.create_matrix_elems(&mut self.solver.mat);
519 self.solver.comps.push(r.into());
520 self.state.ric.push(self.solver.comps.len() - 1);
521 let mut v = Vsrc::new(val, 0.0, Some(fnode), None, ivar);
522 v.create_matrix_elems(&mut self.solver.mat);
523 self.solver.comps.push(v.into());
524 self.state.vic.push(self.solver.comps.len() - 1);
525 }
526 pub fn solve(&mut self) -> SpResult<TranResult> {
527 let mut results = TranResult::new();
529 results.signals(&self.solver.vars);
530
531 let tsoln = self.solver.solve(&AnalysisInfo::OP);
533 let tdata = match tsoln {
534 Ok(x) => x,
535 Err(e) => {
536 println!("Failed to find initial solution");
537 return Err(e);
538 }
539 };
540 results.push(self.state.t, &tdata);
541
542 for c in self.state.vic.iter() {
545 self.solver.comps[*c].update(0.0);
546 }
547 for c in self.state.ric.iter() {
548 self.solver.comps[*c].update(1e-9);
549 }
550
551 let mut tpoint: usize = 0;
552 let max_tpoints: usize = 1e9 as usize;
553 self.state.t = self.opts.tstep;
554 self.state.dt = self.opts.tstep;
555 while self.state.t < self.opts.tstop && tpoint < max_tpoints {
556 let aninfo = AnalysisInfo::TRAN(&self.opts, &self.state);
557 let tsoln = self.solver.solve(&aninfo);
558 let tdata = match tsoln {
559 Ok(x) => x,
560 Err(e) => {
561 println!("Failed at t={}", self.state.t);
562 return Err(e);
563 }
564 };
565 results.push(self.state.t, &tdata);
566
567 tpoint += 1;
569 self.state.t += self.opts.tstep;
570 }
571 results.end();
572 Ok(results)
573 }
574}
575#[derive(Default, Serialize, Deserialize)]
578pub struct TranResult {
579 pub signals: Vec<String>,
580 pub time: Vec<f64>,
581 pub data: Vec<Vec<f64>>,
582 pub map: HashMap<String, Vec<f64>>,
583}
584impl TranResult {
585 pub fn new() -> Self {
586 Self {
587 signals: vec![],
588 time: vec![],
589 data: vec![],
590 map: HashMap::new(),
591 }
592 }
593 fn signals(&mut self, vars: &Variables<f64>) {
594 for name in vars.names.iter() {
595 self.signals.push(name.to_string());
596 }
597 }
598 fn push(&mut self, t: f64, vals: &Vec<f64>) {
599 self.time.push(t);
600 self.data.push(vals.clone());
601 }
603 fn end(&mut self) {
605 self.map.insert("time".to_string(), self.time.clone());
606 for i in 0..self.signals.len() {
607 let mut vals: Vec<f64> = vec![];
608 for v in 0..self.time.len() {
609 vals.push(self.data[v][i]);
610 }
611 self.map.insert(self.signals[i].clone(), vals);
612 }
613 }
614 pub fn len(&self) -> usize {
615 self.time.len()
616 }
617 pub fn get(&self, name: &str) -> SpResult<&Vec<f64>> {
619 match self.map.get(name) {
620 Some(v) => Ok(v),
621 None => Err(sperror(format!("Signal Not Found: {}", name))),
622 }
623 }
624}
625impl Index<usize> for TranResult {
628 type Output = Vec<f64>;
629 fn index(&self, t: usize) -> &Vec<f64> {
630 &self.data[t]
631 }
632}
633
634pub fn tran(ckt: Ckt, opts: Option<Options>, args: Option<TranOptions>) -> SpResult<TranResult> {
636 let o = if let Some(val) = opts { val } else { Options::default() };
637 let a = if let Some(val) = args { val } else { TranOptions::default() };
638 return Tran::new(ckt, o, a).solve();
639}
640
641pub struct Options {
643 pub temp: f64,
644 pub tnom: f64,
645 pub gmin: f64,
646 pub iabstol: f64,
647 pub reltol: f64,
648 pub chgtol: f64,
649 pub volt_tol: f64,
650 pub trtol: usize,
651 pub tran_max_iter: usize,
652 pub dc_max_iter: usize,
653 pub dc_trcv_max_iter: usize,
654 pub integrate_method: usize,
655 pub order: usize,
656 pub max_order: usize,
657 pub pivot_abs_tol: f64,
658 pub pivot_rel_tol: f64,
659 pub src_factor: f64,
660 pub diag_gmin: f64,
661}
662
663use crate::proto;
664
665impl From<proto::SimOptions> for Options {
666 fn from(i: proto::SimOptions) -> Self {
667 Self {
668 temp: if let Some(val) = i.temp { val } else { 300.15 },
669 tnom: if let Some(val) = i.tnom { val } else { 300.15 },
670 gmin: if let Some(val) = i.gmin { val } else { 1e-12 },
671 iabstol: if let Some(val) = i.iabstol { val } else { 1e-12 },
672 reltol: if let Some(val) = i.reltol { val } else { 1e-3 },
673 chgtol: 1e-14,
674 volt_tol: 1e-6,
675 trtol: 7,
676 tran_max_iter: 10,
677 dc_max_iter: 100,
678 dc_trcv_max_iter: 50,
679 integrate_method: 0,
680 order: 1,
681 max_order: 2,
682 pivot_abs_tol: 1e-13,
683 pivot_rel_tol: 1e-3,
684 src_factor: 1.0,
685 diag_gmin: 0.0,
686 }
687 }
688}
689impl Default for Options {
690 fn default() -> Self {
691 Self::from(proto::SimOptions::default())
692 }
693}
694
695#[derive(Default)]
696pub(crate) struct AcState {
697 pub omega: f64,
698}
699
700pub struct AcOptions {
702 pub fstart: usize,
703 pub fstop: usize,
704 pub npts: usize, }
706impl From<proto::AcOptions> for AcOptions {
707 fn from(i: proto::AcOptions) -> Self {
708 Self {
709 fstart: i.fstart as usize,
710 fstop: i.fstop as usize,
711 npts: i.npts as usize,
712 }
713 }
714}
715impl Default for AcOptions {
716 fn default() -> Self {
717 Self::from(proto::AcOptions::default())
718 }
719}
720
721#[derive(Default, Serialize, Deserialize)]
724pub struct AcResult {
725 pub signals: Vec<String>,
726 pub freq: Vec<f64>,
727 pub data: Vec<Vec<Complex<f64>>>,
728 pub map: HashMap<String, Vec<Complex<f64>>>,
729}
730impl AcResult {
731 fn new() -> Self {
732 Self::default()
733 }
734 fn signals<T>(&mut self, vars: &Variables<T>) {
735 for name in vars.names.iter() {
736 self.signals.push(name.to_string());
737 }
738 }
739 fn push(&mut self, f: f64, vals: &Vec<Complex<f64>>) {
740 self.freq.push(f);
741 self.data.push(vals.clone());
742 }
744 fn end(&mut self) {
746 for i in 0..self.signals.len() {
748 let mut vals: Vec<Complex<f64>> = vec![];
749 for v in 0..self.freq.len() {
750 vals.push(self.data[v][i]);
751 }
752 self.map.insert(self.signals[i].clone(), vals);
753 }
754 }
755 pub fn len(&self) -> usize {
756 self.freq.len()
757 }
758}
759
760pub fn ac(ckt: Ckt, opts: Option<Options>, args: Option<AcOptions>) -> SpResult<AcResult> {
762 use serde::ser::{SerializeSeq, Serializer};
768 use std::fs::File;
769
770 let opts = if let Some(val) = opts { val } else { Options::default() };
771 let args = if let Some(val) = args { val } else { AcOptions::default() };
772
773 let mut solver = Solver::<f64>::new(ckt, opts);
775 let _dc_soln = solver.solve(&AnalysisInfo::OP)?;
776
777 let mut solver = Solver::<Complex<f64>>::from(solver);
779 let mut state = AcState::default();
780 let mut soln = vec![];
781
782 let rf = File::create("stream.ac.json").unwrap(); let mut ser = serde_json::Serializer::new(rf);
785 let mut seq = ser.serialize_seq(None).unwrap();
786
787 let mut results = AcResult::new();
789 results.signals(&solver.vars);
790
791 let mut f = args.fstart as f64;
793 let fstop = args.fstop as f64;
794 let fstep = (10.0).powf(f64::log10(fstop / f) / args.npts as f64);
795
796 while f <= fstop {
798 use std::f64::consts::PI;
799 state.omega = 2.0 * PI * f;
800 let an = AnalysisInfo::AC(&args, &state);
801 let fsoln = solver.solve(&an)?;
802
803 results.push(f, &fsoln);
805 let mut flat: Vec<f64> = vec![f];
807 for pt in fsoln.iter() {
808 flat.push(pt.re);
809 flat.push(pt.im);
810 }
811 seq.serialize_element(&flat).unwrap();
812 soln.push(fsoln);
814 if f == fstop {
816 break;
817 }
818 f = f64::min(f * fstep, fstop);
819 }
820 SerializeSeq::end(seq).unwrap();
822
823 use std::io::prelude::*;
825 let mut rfj = File::create("ac.json").unwrap(); let s = serde_json::to_string(&results).unwrap();
827 rfj.write_all(s.as_bytes()).unwrap();
828
829 results.end();
831 return Ok(results);
832}