Skip to content

Commit 3b32f8f

Browse files
committed
Merge branch 'release-0.7.4'
2 parents 1d3cde8 + 2f9f993 commit 3b32f8f

File tree

8 files changed

+135
-42
lines changed

8 files changed

+135
-42
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ language: julia
22
julia:
33
- 0.6
44
- 0.7
5+
- nightly
56
notifications:
67
email: false
78
webhooks:
@@ -27,9 +28,9 @@ after_success:
2728
using Pkg # `using Pkg` and `pkg"..."` must be in separate if blocks
2829
end
2930
@static if VERSION >= v"0.7.0-DEV.3656"
30-
pkg"add Documenter@0.13.2"
31+
pkg"add Documenter@0.19.0"
3132
else
32-
Pkg.add("Documenter", v"0.13.2", v"0.13.2+")
33+
Pkg.add("Documenter", v"0.19.0", v"0.19.0+")
3334
cd(Pkg.dir("ACME"))
3435
end
3536
include(joinpath("docs", "make.jl"))'

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ACME.jl - Analog Circuit Modeling and Emulation for Julia
22

33
[![Join the chat at https://gitter.im/HSU-ANT/ACME.jl](https://badges.gitter.im/HSU-ANT/ACME.jl.svg)](https://gitter.im/HSU-ANT/ACME.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4-
[![Documentation](https://img.shields.io/badge/docs-v0.7.3-blue.svg)](https://hsu-ant.github.io/ACME.jl/v0.7.3)
4+
[![Documentation](https://img.shields.io/badge/docs-v0.7.4-blue.svg)](https://hsu-ant.github.io/ACME.jl/v0.7.4)
55

66
ACME is a [Julia](http://julialang.org/) package for the simulation of
77
electrical circuits, focusing on audio effect circuits. It allows to
@@ -122,7 +122,7 @@ fail to run altogether.
122122

123123
## Moving on
124124

125-
There is some [documentation](https://hsu-ant.github.io/ACME.jl/v0.7.3)
125+
There is some [documentation](https://hsu-ant.github.io/ACME.jl/v0.7.4)
126126
available for how
127127
to use ACME. Additionally, you can take a look at the examples that can be found
128128
in the `examples` directory below `Pkg.dir("ACME")`.

REQUIRE

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
julia 0.6
2-
Compat 0.65.0
2+
Compat 1.0.0
33
DataStructures 0.2.9
44
IterTools 0.1.0
55
ProgressMeter 0.2.1
6-
StatsBase 0.23.0

docs/src/gettingstarted.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,16 @@ This will download ACME and all of its dependencies.
1919
We will demonstrate ACME by modeling a simple diode clipper. The first step is
2020
to load ACME:
2121

22-
```Julia
22+
```jldoctest firststeps; output = false
2323
using ACME
24+
25+
# output
26+
2427
```
2528

2629
Now we create the circuit description:
2730

28-
```Julia
31+
```jldoctest firststeps; output = false, filter = r"(ACME\.)?Circuit\(.*"s
2932
circ = @circuit begin
3033
j_in = voltagesource()
3134
r1 = resistor(1e3)
@@ -38,6 +41,10 @@ circ = @circuit begin
3841
r1[2] ⟷ c1[1] ⟷ d1[+] ⟷ d2[-] ⟷ j_out[+]
3942
gnd ⟷ c1[2] ⟷ d1[-] ⟷ d2[+] ⟷ j_out[-]
4043
end
44+
45+
# output
46+
47+
Circuit(...)
4148
```
4249

4350
The first six lines inside the `begin`/`end` block instantiate circuit elements.
@@ -63,7 +70,7 @@ It is also possible to specify connections following the element definition
6370
one can only connect to elements defined before. Thus, above circuit could also
6471
be entered as:
6572

66-
```Julia
73+
```jldoctest firststeps; output = false, filter = r"(ACME\.)?Circuit\(.*"s
6774
circ = @circuit begin
6875
j_in = voltagesource(), [-] ⟷ gnd
6976
r1 = resistor(1e3), [1] ⟷ j_in[+]
@@ -72,24 +79,38 @@ circ = @circuit begin
7279
d2 = diode(is=1.8e-15), [+] ⟷ gnd, [-] ⟷ r1[2]
7380
j_out = voltageprobe(), [+] ⟷ r1[2], [-] ⟷ gnd
7481
end
82+
83+
# output
84+
85+
Circuit(...)
7586
```
7687

7788
Now that the circuit has been set up, we need to turn it into a model. This
7889
could hardly be any easier:
7990

80-
```Julia
81-
model = DiscreteModel(circ, 1./44100)
91+
```jldoctest firststeps; output = false, filter = r"(ACME\.)?DiscreteModel{.*"s
92+
model = DiscreteModel(circ, 1/44100)
93+
94+
# output
95+
96+
DiscreteModel{...}(...)
8297
```
8398

8499
The second argument specifies the sampling interval, the reciprocal of the
85100
sampling rate, here assumed to be the typical 44100 Hz.
86101

87102
Now we can process some input data. It has to be provided as a matrix with one
88103
row per input (just one in the example) and one column per sample. So for a
89-
sinusoid at 1 kHz lasting one second, we do::
104+
sinusoid at 1 kHz lasting one second, we do:
90105

91-
```Julia
92-
y = run!(model, sin(2π*1000/44100*(0:44099)'))
106+
```jldoctest firststeps; filter = r"\r?Running model:.*"
107+
y = run!(model, sin.(2π*1000/44100*(0:44099)'))
108+
109+
# output
110+
111+
Running model: 100%|████████████████████████████████████| Time: 0:00:01
112+
1×44100 Array{Float64,2}:
113+
0.0 0.0275964 0.0990996 0.195777 … -0.537508 -0.462978 -0.36521
93114
```
94115

95116
The output `y` now likewise is a matrix with one row for the one probe we have

docs/src/ug.md

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ disconnect!
2424
```
2525

2626
For example, a cascade of 20 RC-lowpasses could be generated by:
27-
```julia
27+
```jldoctest ug; output = false, setup = :(using ACME)
2828
circ = @circuit begin
2929
src = voltagesource(), [-] ⟷ gnd
3030
output = voltageprobe(), [-] ⟷ gnd
@@ -36,9 +36,12 @@ for i in 1:20
3636
connect!(circ, (resrefdes, 1), pin)
3737
connect!(circ, (resrefdes, 2), (caprefdes, 1))
3838
connect!(circ, (caprefdes, 2), :gnd)
39-
pin = (resrefdes, 2)
39+
global pin = (resrefdes, 2)
4040
end
4141
connect!(circ, pin, (:output, +))
42+
43+
# output
44+
4245
```
4346

4447
## Model Creation and Use
@@ -47,35 +50,63 @@ A `Circuit` only stores elements and information about their connections. To
4750
simulate a circuit, a model has to be derived from it. This can be as simple
4851
as:
4952

50-
```Julia
53+
```jldoctest ug; output = false, filter = r"(ACME\.)?DiscreteModel{.*"s
5154
model = DiscreteModel(circ, 1/44100)
55+
56+
# output
57+
58+
DiscreteModel{...}(...)
5259
```
5360

5461
Here, `1/44100` denotes the sampling interval, i.e. the reciprocal of the
5562
sampling rate at which the model should run. Optionally, one can specify the
5663
solver to use for solving the model's non-linear equation:
5764

58-
```Julia
65+
```jldoctest ug; output = false, filter = r"(ACME\.)?DiscreteModel{.*"s
5966
model = DiscreteModel(circ, 1/44100, HomotopySolver{SimpleSolver})
67+
68+
# output
69+
70+
DiscreteModel{...}(...)
6071
```
6172

6273
See [Solvers](@ref) for more information about the available solvers.
6374

6475
Once a model is created, it can be run:
6576

66-
```Julia
77+
```jldoctest; output = false, setup = :(using ACME; model=DiscreteModel(@circuit(begin end), 1); u=zeros(0,10))
6778
y = run!(model, u)
79+
80+
# output
81+
82+
0×10 Array{Float64,2}
6883
```
6984

7085
The input `u` is matrix with one row for each of the circuit's inputs and one
7186
column for each time step to simulate. Likewise, the output `y` will be a
7287
matrix with one row for each of the circuit's outputs and one column for each
7388
simulated time step. The order of the rows will correspond to the order in which
74-
the respective input and output elements were added to the `Circuit`. To
89+
the respective input and output elements were added to the `Circuit`.
90+
So for above circuit, we may obtain the first 100 samples of the impulse
91+
response with
92+
93+
```jldoctest ug
94+
run!(model, [1 zeros(1,99)])
95+
96+
# output
97+
98+
1×100 Array{Float64,2}:
99+
1.83357e-8 3.1622e-7 2.59861e-6 … 0.00465423 0.00459275 0.00453208
100+
```
101+
To
75102
simulate a circuit without inputs, a matrix with zero rows may be passed:
76103

77-
```Julia
104+
```jldoctest; output = false, setup = :(using ACME; model=DiscreteModel(@circuit(begin end), 1))
78105
y = run!(model, zeros(0, 100))
106+
107+
# output
108+
109+
0×100 Array{Float64,2}
79110
```
80111

81112
The internal state of the model (e.g. capacitor charges) is preserved accross
@@ -85,9 +116,12 @@ Each invocation of `run!` in this way has to allocate some memory as temporary
85116
storage. To avoid this overhead when running the same model for many small input
86117
blocks, a `ModelRunner` instance can be created explicitly:
87118

88-
```Julia
119+
```jldoctest ug; output = false, setup = :(u=zeros(1,10); y=zeros(1,10))
89120
runner = ModelRunner(model, false)
90121
run!(runner, y, u)
122+
123+
# output
124+
91125
```
92126

93127
By using a pre-allocated output `y` as in the example, allocations in `run!` are
@@ -97,8 +131,32 @@ Upon creation of a `DiscreteModel`, its internal states (e.g. capacitor charges)
97131
are set to zero. It is also possible to set the states to a steady state (if
98132
one can be found) with:
99133

100-
```Julia
134+
```jldoctest ug; output = false
101135
steadystate!(model)
136+
137+
# output
138+
139+
20-element Array{Float64,1}:
140+
0.0
141+
0.0
142+
0.0
143+
0.0
144+
0.0
145+
0.0
146+
0.0
147+
0.0
148+
0.0
149+
0.0
150+
0.0
151+
0.0
152+
0.0
153+
0.0
154+
0.0
155+
0.0
156+
0.0
157+
0.0
158+
0.0
159+
0.0
102160
```
103161

104162
This is often desirable for circuits where bias voltages are only slowly

src/ACME.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ np(model::DiscreteModel, subidx) = size(model.dqs[subidx], 1)
460460
nu(model::DiscreteModel) = size(model.b, 2)
461461
ny(model::DiscreteModel) = length(model.y0)
462462
nn(model::DiscreteModel, subidx) = size(model.fqs[subidx], 2)
463-
nn(model::DiscreteModel) = reduce(+, 0, size(fq, 2) for fq in model.fqs)
463+
nn(model::DiscreteModel) = Compat.reduce(+, init=0, size(fq, 2) for fq in model.fqs)
464464

465465
function steadystate(model::DiscreteModel, u=zeros(nu(model)))
466466
@static if VERSION < v"0.7.0-DEV.5211"
@@ -528,8 +528,8 @@ function linearize(model::DiscreteModel, usteady::AbstractVector{Float64}=zeros(
528528

529529
zranges[idx] = zoff:zoff+length(zsub)-1
530530
fqdzdps = [model.fqprevs[idx][:,zranges[n]] * dzdps[n] for n in 1:idx-1]
531-
dqlins[idx] = reduce(+, model.dqs[idx], fqdzdps .* dqlins[1:idx-1])
532-
eqlins[idx] = reduce(+, model.eqs[idx], fqdzdps .* eqlins[1:idx-1])
531+
dqlins[idx] = Compat.reduce(+, init=model.dqs[idx], fqdzdps .* dqlins[1:idx-1])
532+
eqlins[idx] = Compat.reduce(+, init=model.eqs[idx], fqdzdps .* eqlins[1:idx-1])
533533

534534
x0 += model.c[:,zranges[idx]] * (zsub - dzdps[idx]*psteady)
535535
a += model.c[:,zranges[idx]] * dzdps[idx] * dqlins[idx]
@@ -716,19 +716,19 @@ function gensolve(a, b, x, h, thresh=0.1)
716716
if m == 0
717717
return x, h
718718
end
719-
t = sortperm(vec(mapslices(ait -> count(!iszero, ait), a, 2))) # row indexes in ascending order of nnz
719+
t = sortperm(vec(mapslices(ait -> count(!iszero, ait), a, dims=2))) # row indexes in ascending order of nnz
720720
tol = 3 * max(eps(float(eltype(a))), eps(float(eltype(h)))) * size(a, 2)
721721
for i in 1:m
722722
ait = a[t[i],:]' # ait is a row of the a matrix
723723
s = ait * h;
724-
inz, jnz, nz_vals = findnz(s)
724+
jnz, nz_vals = findnz(s')
725725
nz_abs_vals = abs.(nz_vals)
726-
max_abs_val = reduce(max, zero(eltype(s)), nz_abs_vals)
726+
max_abs_val = Compat.reduce(max, init=zero(eltype(s)), nz_abs_vals)
727727
if max_abs_val tol # cosidered numerical zero
728728
continue
729729
end
730730
jat = jnz[nz_abs_vals .≥ thresh*max_abs_val] # cols above threshold
731-
j = jat[argmin(vec(mapslices(hj -> count(!iszero, hj), h[:,jat], 1)))]
731+
j = jat[argmin(vec(mapslices(hj -> count(!iszero, hj), h[:,jat], dims=1)))]
732732
q = h[:,j]
733733
x = x + convert(typeof(x), q * ((b[t[i],:]' - ait*x) * (1 / (ait*q))))
734734
if size(h)[2] > 1

0 commit comments

Comments
 (0)