Skip to content

Commit a4bd550

Browse files
authored
Progress bars (#20)
* progress bars added * Symbolics updated
1 parent 25141c4 commit a4bd550

File tree

7 files changed

+35
-19
lines changed

7 files changed

+35
-19
lines changed

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "HarmonicBalance"
22
uuid = "e13b9ff6-59c3-11ec-14b1-f3d2cc6c135e"
33
authors = ["Jan Kosata <kosataj@phys.ethz.ch>", "Javier del Pino <jdelpino@phys.ethz.ch>"]
4-
version = "0.4.3"
4+
version = "0.4.4"
55

66
[deps]
77
BijectiveHilbert = "91e7fc40-53cd-4118-bd19-d7fcd1de2a54"
@@ -18,6 +18,7 @@ Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316"
1818
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1919
Peaks = "18e31ff7-3703-566c-8e60-38913d67486b"
2020
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
21+
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
2122
PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
2223
PyPlot = "d330b81b-6aea-500a-939a-2ce795aea3ee"
2324
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
@@ -37,10 +38,11 @@ HomotopyContinuation = "2.6.4"
3738
JLD2 = "0.4.19"
3839
Latexify = "0.15.9"
3940
Peaks = "0.4.0"
41+
ProgressMeter = "1.7.2"
4042
PyCall = "1.93.0"
4143
PyPlot = "2.10.0"
4244
SymbolicUtils = "0.19.7"
43-
Symbolics = "4.3.1"
45+
Symbolics = "4.4.1"
4446
julia = "1.7.0"
4547

4648
[extras]

src/HarmonicBalance.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module HarmonicBalance
88
export d
99
export plot
1010
using Symbolics
11+
using ProgressMeter
1112
import SymbolicUtils: Term, Add, Div, Mul, Pow, Sym
1213
using DocStringExtensions
1314

src/modules/LinearResponse.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module LinearResponse
77
using ..HarmonicBalance
88
using ..HC_wrapper
99
using PyPlot
10+
using ProgressMeter
1011
using DocStringExtensions
1112
using Latexify
1213

src/modules/LinearResponse/jacobian_spectrum.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,12 @@ function plot_jacobian_spectrum(res::Result, nat_var::Num; Ω_range, branch::Int
144144
spectra = [JacobianSpectrum(res, branch=branch, index = i) for i in (1:length(res.solutions))[stability]]
145145
C = Array{Float64, 2}(undef, length(Ω_range)-1, length(X)-1)
146146

147+
bar = Progress(length(CartesianIndices(C)), 1, "Diagonalizing the Jacobian for each solution ... ", 50)
147148
for ij in CartesianIndices(C)
148149
C[ij] = abs(evaluate(spectra[ij[2]][nat_var], Ω_range[ij[1]] - offset[ij[2]]))
150+
next!(bar)
149151
end
152+
150153
x_mat = x_scale * hcat([x*ones(length(Ω_range)) for x in X]...)
151154
y_mat = y_scale * hcat([Ω_range for j=1:length(X)]...)
152155
C = logscale ? log.(C) : C

src/modules/LinearResponse/linear_response.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ function plot_response(res::Result, Ω_range; branch::Int, logscale=false)
7979
Y = Array{Float64, 2}(undef, length(Ω_range), length(X))
8080

8181
# this could be optimized by not grabbing the entire huge dictionary every time
82+
83+
bar = Progress(length(Y), 1, "Solving the linear response ODE for each solution and input frequency ... ", 50)
8284
for j in 1:(size(Y)[2])
85+
next!(bar)
8386
s = get_single_solution(res, branch=branch, index=j)
8487
for i in 1:(size(Y)[1])
8588
Y[i,j] = get_response(response, s, reverse(Ω_range)[i])

src/solve_homotopy.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ get_single_solution(res::Result, index) = [get_single_solution(res, index=index,
3636
fixed_parameters::ParameterList;
3737
random_warmup=false,
3838
threading=false,
39-
sorting="hilbert",
40-
show_progress=true)
39+
sorting="hilbert")
4140
4241
Solves `prob` over the ranges specified by `swept_parameters`, keeping `fixed_parameters` constant.
4342
`swept_parameters` accepts pairs mapping symbolic variables to arrays or `LinRange`.
@@ -48,7 +47,6 @@ Keyword arguments
4847
This takes far longer but can be more reliable.
4948
- `threading`: If `true`, multithreaded support is activated. The number of available threads is set by the environment variable `JULIA_NUM_THREADS`.
5049
- `sorting`: the method used by `sort_solutions` to get continuous solutions branches. The current options are `"hilbert"` (1D sorting along a Hilbert curve), `"nearest"` (nearest-neighbor sorting) and `"none"`.
51-
- `show_progress`: If `true` Indicate whether a progress bar should be displayed (see [HomotopyContinuation.jl docs](https://www.juliahomotopycontinuation.org/HomotopyContinuation.jl/stable/solve/)
5250
5351
Example: solving a simple harmonic oscillator ``m \\ddot{x} + γ \\dot{x} + ω_0^2 x = F \\cos(ωt)``
5452
to obtain the response as a function of ``ω``
@@ -86,7 +84,7 @@ A steady state result for 1000 parameter points
8684
```
8785
8886
"""
89-
function get_steady_states(prob::Problem, swept_parameters::ParameterRange, fixed_parameters::ParameterList; random_warmup=false, threading=false, sorting="nearest",show_progress=true)
87+
function get_steady_states(prob::Problem, swept_parameters::ParameterRange, fixed_parameters::ParameterList; random_warmup=false, threading=false, sorting="nearest")
9088
# make sure the variables are in our namespace to make them accessible later
9189
declare_variable.(string.(cat(prob.parameters, prob.variables, dims=1)))
9290

@@ -95,7 +93,7 @@ function get_steady_states(prob::Problem, swept_parameters::ParameterRange, fixe
9593
unique_fixed = filter_duplicate_parameters(swept_parameters, fixed_parameters)
9694
input_array = _prepare_input_params(prob, swept_parameters, unique_fixed)
9795
# feed the array into HomotopyContinuation, get back an similar array of solutions
98-
raw = _get_raw_solution(prob, input_array, sweep=swept_parameters, random_warmup=random_warmup, threading=threading,show_progress=show_progress)
96+
raw = _get_raw_solution(prob, input_array, sweep=swept_parameters, random_warmup=random_warmup, threading=threading)
9997

10098
# extract all the information we need from results
10199
#rounded_solutions = unique_points.(HomotopyContinuation.solutions.(getindex.(raw, 1)); metric = EuclideanNorm(), atol=1E-14, rtol=1E-8)
@@ -228,20 +226,22 @@ end
228226

229227

230228
"Uses HomotopyContinuation to solve `problem` at specified `parameter_values`."
231-
function _get_raw_solution(problem::Problem, parameter_values::Array{ParameterVector}; sweep=[],random_warmup=false, threading=false,show_progress= true)
229+
function _get_raw_solution(problem::Problem, parameter_values::Array{ParameterVector}; sweep=[],random_warmup=false, threading=false)
232230
# HomotopyContinuation accepts 1D arrays of parameter sets
233231
params_1D = reshape(parameter_values, :, 1)
234232

235233
if random_warmup
236234
complex_pert = [1E-2 * issubset(p, keys(sweep))*randn(ComplexF64) for p in problem.parameters] # complex perturbation of the warmup parameters
237235
warmup_parameters = params_1D[Int(round(length(params_1D)/2))] .* (ones(length(params_1D[1])) + complex_pert)
238-
warmup_solution = HomotopyContinuation.solve(problem.system, target_parameters=warmup_parameters, threading=threading, show_progress=show_progress)
239-
result_full = HomotopyContinuation.solve(problem.system, HomotopyContinuation.solutions(warmup_solution), start_parameters=warmup_parameters, target_parameters=parameter_values, threading=threading,show_progress= show_progress)
236+
warmup_solution = HomotopyContinuation.solve(problem.system, target_parameters=warmup_parameters, threading=threading)
237+
result_full = HomotopyContinuation.solve(problem.system, HomotopyContinuation.solutions(warmup_solution), start_parameters=warmup_parameters, target_parameters=parameter_values, threading=threading)
240238
else
241239
result_full = Array{Vector{Any}, 1}(undef, length(parameter_values))
240+
bar = Progress(length(parameter_values), 1, "Solving via total degree homotopy ...", 50)
242241
for i in 1:length(parameter_values) # do NOT thread this
243242
p = parameter_values[i]
244-
result_full[i] = [HomotopyContinuation.solve(problem.system, start_system=:total_degree, target_parameters=p, threading=threading, show_progress=show_progress), p]
243+
next!(bar)
244+
result_full[i] = [HomotopyContinuation.solve(problem.system, start_system=:total_degree, target_parameters=p, threading=threading, show_progress=false), p]
245245
end
246246
end
247247

src/sorting.jl

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ Go through a vector of solution and sort each according to Euclidean norm.
113113
function sort_1D(solns::Vector{Vector{SteadyState}})
114114
sorted_solns = similar(solns) # preallocate
115115
sorted_solns[1] = sort(solns[1], by= x->abs.(imag(x))) # prefer real solution at first position
116+
117+
bar = Progress(length(solns), 1, "Ordering solutions into branches ...")
116118
for (i, soln) in enumerate(solns[1:end-1])
119+
next!(bar)
117120
matched_indices = align_pair(sorted_solns[i], solns[i+1]) # pairs of matching indices
118121
next_indices = getindex.(matched_indices, 2) # indices of the next solution
119122
sorted_solns[i+1] = (solns[i+1])[next_indices]
@@ -124,16 +127,16 @@ end
124127
function hilbert_indices(solns::Matrix{Vector{Vector{ComplexF64}}})
125128
"""Get mapping between 2D indexes (parameter space) and a 1D Hilbert curve"""
126129
Lx,Ly = size(solns)
127-
mapping = [] #compute mapping between Hilbert indices and 2Ds
128-
for j in 1:Ly #length of parameter sweep 1
129-
for i in 1:Lx #length of parameter sweep 2
130+
mapping = [] # compute mapping between Hilbert indices and 2Ds
131+
for j in 1:Ly # length of parameter sweep 1
132+
for i in 1:Lx # length of parameter sweep 2
130133
X = [i, j]
131134
h = encode_hilbert(Simple2D(Int), X)
132135
X .= 0
133136
push!(mapping,(h=>decode_hilbert!(Simple2D(Int), X, h)))
134137
end
135138
end
136-
idx_pairs = [el[2] for el in sort(mapping)] #sort along the Hilbert curve. Now we can iterate over these indexes
139+
idx_pairs = [el[2] for el in sort(mapping)] # sort along the Hilbert curve. Now we can iterate over these indexes
137140
end
138141

139142
function naive_indices(solns::Matrix{Vector{Vector{ComplexF64}}})
@@ -164,16 +167,19 @@ end
164167

165168
function sort_2D(solns::Matrix{Vector{Vector{ComplexF64}}}; sorting="nearest")
166169
"""match each 2D solution with all its surrounding neighbors, including the diagonal ones"""
167-
#determine a trajectory in 2D space where nodes will be visited
168-
if sorting=="hilbert" #propagating matching of solutions along a hilbert_curve in 2D
170+
# determine a trajectory in 2D space where nodes will be visited
171+
if sorting=="hilbert" # propagating matching of solutions along a hilbert_curve in 2D
169172
idx_pairs = hilbert_indices(solns)
170-
elseif sorting=="nearest" #propagate matching of solutions along rows
173+
elseif sorting=="nearest" # propagate matching of solutions along rows
171174
idx_pairs = naive_indices(solns)
172175
end
173176

174-
sorted_solns = Inf.*copy(solns) #infinite solutions are ignored by the align_pair function. This trick allows a consistent ordering "propagation"
177+
sorted_solns = Inf.*copy(solns) # infinite solutions are ignored by the align_pair function. This trick allows a consistent ordering "propagation"
175178
sorted_solns[1,1] = sort(solns[1,1], by= x->abs.(imag(x))) # prefer real solution at first position
179+
180+
bar = Progress(length(idx_pairs), 1, "Ordering solutions into branches ...")
176181
for i in 1:length(idx_pairs)-1
182+
next!(bar)
177183
neighbors = get_nn_2D(idx_pairs[i+1],size(solns,1),size(solns,2))
178184
reference = [sorted_solns[ind...] for ind in neighbors]
179185
matched_indices = align_pair(reference, solns[idx_pairs[i+1]...]) # pairs of matching indices

0 commit comments

Comments
 (0)