1use dune_raw::{Data, VarType};
6use num_complex::Complex64;
7
8use crate::circuit::{Circuit, VarKind, Vars};
9use crate::engine::{AcStepType, Engine};
10use crate::error::Error;
11use crate::options::Options;
12use crate::solution::Solution;
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub enum AcSweep {
17 Decade,
19 Octave,
21 Linear,
23}
24
25#[derive(Clone, Debug)]
27pub struct Ac {
28 pub solution: Solution,
29 pub notes: Vec<String>,
30}
31
32impl Circuit {
33 pub fn ac(
35 &self,
36 opts: &Options,
37 sweep: AcSweep,
38 points: usize,
39 fstart: f64,
40 fstop: f64,
41 ) -> Result<Ac, Error> {
42 let ok = fstart > 0.0 && fstart.is_finite() && fstop.is_finite() && fstop >= fstart;
43 if !ok {
44 return Err(Error::Build(".ac frequencies are inconsistent".into()));
45 }
46 let built = self.build(opts)?;
47 let notes = built.notes.clone();
48 let mut engine = Engine::new(built);
49 let step_type = match sweep {
50 AcSweep::Decade => AcStepType::Decade,
51 AcSweep::Octave => AcStepType::Octave,
52 AcSweep::Linear => AcStepType::Linear,
53 };
54 let rows = engine.ac(opts, step_type, points, fstart, fstop)?;
55
56 let (variables, columns) = ac_columns(&engine.vars, &rows);
57 Ok(Ac {
58 solution: Solution {
59 plotname: "AC Analysis".to_string(),
60 variables,
61 data: Data::Complex(columns),
62 scale: Some(0),
63 },
64 notes,
65 })
66 }
67}
68
69pub(crate) fn ac_columns(
73 vars: &Vars,
74 rows: &[(f64, Vec<Complex64>)],
75) -> (Vec<(String, VarType)>, Vec<Vec<Complex64>>) {
76 let mut variables = vec![("frequency".to_string(), VarType::Frequency)];
77 let mut columns: Vec<Vec<Complex64>> =
78 vec![rows.iter().map(|(f, _)| Complex64::new(*f, 0.0)).collect()];
79 for i in 1..vars.len() {
80 let name = &vars.names[i];
81 match vars.kinds[i] {
82 VarKind::Node if crate::circuit::saved_node(name) => {
83 variables.push((format!("v({name})"), VarType::Voltage));
84 columns.push(rows.iter().map(|(_, sol)| sol[i]).collect());
85 }
86 VarKind::Branch => {
87 variables.push((format!("i({name})"), VarType::Current));
88 columns.push(rows.iter().map(|(_, sol)| sol[i]).collect());
89 }
90 _ => {}
91 }
92 }
93 (variables, columns)
94}