1- export Array_QuEuler, prepare_init_state, solve_QuEuler
1+ export array_qudiff, prepare_init_state, LDEMSAlgHHL, bval, aval
2+ export QuEuler, QuLeapfrog, QuAB2, QuAB3, QuAB4
3+ export QuLDEMSProblem
24
5+ using DiffEqBase
36"""
47 Based on : arxiv.org/abs/1010.2745v2
58
6- QuArray_Euler(N_t,N,h,A)
7- prepare_init_state(b,x,h,N_t)
9+ * array_qudiff(N_t,N,h,A) - generates matrix for k-step solver
10+ * prepare_init_state(b,x,h,N_t) - generates inital states
11+ * solve_qudiff - solver
812
913 x' = Ax + b
1014
@@ -15,72 +19,139 @@ export Array_QuEuler, prepare_init_state, solve_QuEuler
1519 * h - step size.
1620 * tspan - time span.
1721"""
18- function prepare_init_state (tspan:: Tuple ,x:: Vector ,h:: Float64 ,g:: Function )
19- init_state = x;
20- N_t = round (2 * (tspan[2 ] - tspan[1 ])/ h + 3 )
21- b = similar (g (1 ))
22- for i = 1 : N_t
23- if i < (N_t+ 1 )/ 2
24- b = g (h* i + tspan[1 ])
25- init_state = [init_state;h* b]
26- else
27- init_state = [init_state;zero (b)]
28- end
29-
30- end
31- init_state = [init_state;zero (init_state)]
32- init_state
22+
23+ """
24+ LDEMSAlgHHL
25+ * step - step for multistep method
26+ * α - coefficients for xₙ
27+ * β - coefficent for xₙ'
28+ """
29+ abstract type QuODEAlgorithm <: DiffEqBase.AbstractODEAlgorithm end
30+ # abstract type QuODEProblem{uType,tType,isinplace} <: DiffEqBase.AbstractODEProblem{uType,tType,isinplace} end
31+ abstract type LDEMSAlgHHL <: QuODEAlgorithm end
32+
33+ struct QuLDEMSProblem{F,C,U,T} # <: QuODEProblem{uType,tType,isinplace}
34+ A:: F
35+ b:: C
36+ u0:: U
37+ tspan:: NTuple{2,T}
38+
39+ # function QuLDEMSProblem(A,b,u0,tspan)
40+ # new{typeof(u0),typeof(tspan),false,typeof(A),typeof(b)}(A,b,u0,tspan)
41+ # end
3342end
3443
35- function Array_QuEuler (tspan:: Tuple ,h:: Float64 ,g:: Function )
36- N_t = round (2 * (tspan[2 ] - tspan[1 ])/ h + 3 )
37- I_mat = Matrix {Float64} (I, size (g (1 )));
38- A_ = I_mat;
39- zero_mat = zero (I_mat);
40- tmp_A = Array {Float64,2} (undef,size (g (1 )))
41-
42- for j = 2 : N_t + 1
43- A_ = [A_ zero_mat]
44- end
45-
46- for i = 2 : N_t+ 1
47- tmp_A = g (i* h + tspan[1 ])
48- tmp_A = - 1 * (I_mat + h* tmp_A)
49- tA_ = copy (zero_mat)
50- if i< 3
51- tA_ = [tmp_A I_mat]
52- else
53- for j = 1 : i- 3
54- tA_ = [tA_ zero_mat]
55- end
56- if i < (N_t + 1 )/ 2 + 1
57- tA_ = [tA_ tmp_A I_mat]
58- else
59- tA_ = [tA_ - 1 * I_mat I_mat]
60- end
44+ """
45+ Explicit Linear Multistep Methods
46+ """
47+ struct QuEuler{T}<: LDEMSAlgHHL
48+ step:: Int
49+ α:: Vector{T}
50+ β:: Vector{T}
51+
52+ QuEuler (:: Type{T} = Float64) where {T} = new {T} (1 ,[1.0 ,],[1.0 ,])
53+ end
54+
55+ struct QuLeapfrog{T}<: LDEMSAlgHHL
56+ step:: Int
57+ α:: Vector{T}
58+ β:: Vector{T}
59+
60+ QuLeapfrog (:: Type{T} = Float64) where {T} = new {T} (2 ,[0 , 1.0 ],[2.0 , 0 ])
61+ end
62+ struct QuAB2{T}<: LDEMSAlgHHL
63+ step:: Int
64+ α:: Vector{T}
65+ β:: Vector{T}
66+
67+ QuAB2 (:: Type{T} = Float64) where {T} = new {T} (2 ,[1.0 , 0 ], [1.5 , - 0.5 ])
68+ end
69+ struct QuAB3{T}<: LDEMSAlgHHL
70+ step:: Int
71+ α:: Vector{T}
72+ β:: Vector{T}
73+ QuAB3 (:: Type{T} = Float64) where {T} = new {T} (3 ,[1.0 , 0 , 0 ], [23 / 12 , - 16 / 12 , 5 / 12 ])
74+ end
75+ struct QuAB4{T}<: LDEMSAlgHHL
76+ step:: Int
77+ α:: Vector{T}
78+ β:: Vector{T}
79+
80+ QuAB4 (:: Type{T} = Float64) where {T} = new {T} (4 ,[1.0 , 0 , 0 , 0 ], [55 / 24 , - 59 / 24 , 37 / 24 , - 9 / 24 ])
81+ end
82+
83+ function bval (alg:: LDEMSAlgHHL ,t,h,g:: Function )
84+ b = zero (g (1 ))
85+ for i in 1 : (alg. step)
86+ b += alg. β[i]* g (t- (i- 1 )* h)
6187 end
62- if i< N_t+ 1
63- for j = i+ 1 : N_t+ 1
64- tA_ = [tA_ zero_mat]
65- end
88+ return b
89+ end
90+
91+ function aval (alg:: LDEMSAlgHHL ,t,h,g:: Function )
92+ sz, = size (g (1 ))
93+ A = Array {ComplexF64} (undef,sz,(alg. step + 1 )* sz)
94+ i_mat = Matrix {Float64} (I, size (g (1 )))
95+ A[1 : sz,sz* (alg. step) + 1 : sz* (alg. step + 1 )] = i_mat
96+ for i in 1 : alg. step
97+ A[1 : sz,sz* (i - 1 ) + 1 : sz* i] = - 1 * (alg. α[alg. step - i + 1 ]* i_mat + h* alg. β[alg. step - i + 1 ]* g (t - (alg. step - i)* h))
6698 end
67- A_ = [A_;tA_]
99+ return A
100+ end
68101
69- end
70- A_ = [zero (A_) A_;A_' zero (A_)]
71- A_
102+ function prepare_init_state (tspan:: NTuple{2, Float64} ,x:: Vector ,h:: Float64 ,g:: Function ,alg:: LDEMSAlgHHL )
103+ N_t = round (Int, (tspan[2 ] - tspan[1 ])/ h + 1 ) # number of time steps
104+ N = nextpow (2 ,2 * N_t + 1 ) # To ensure we have a power of 2 dimension for matrix
105+ sz, = size (g (1 ))
106+ init_state = zeros (ComplexF64,2 * (N)* sz)
107+ # inital value
108+ init_state[1 : sz] = x
109+ for i in 2 : N_t
110+ b = bval (alg,h* (i - 1 ) + tspan[1 ],h,g)
111+ init_state[Int (sz* (i - 1 ) + 1 ): Int (sz* (i))] = h* b
112+ end
113+ return init_state
72114end
73115
74- function solve_QuEuler (A:: Function , b:: Function , x:: Vector ,tspan:: Tuple , h:: Float64 )
75-
76- mat = Array_QuEuler (tspan,h,A)
77- state = prepare_init_state (tspan,x,h,b)
78- λ = maximum (eigvals (mat))
79- C_value = minimum (eigvals (mat) .| > abs)* 0.1 ;
80- n_reg = 12 ;
81- mat = 1 / (λ* 2 )* mat
82- state = state* 1 / (2 * λ) |> normalize!
83- res = hhlsolve (mat,state, n_reg, C_value)
84- res = res/ λ
85- res
116+ function array_qudiff (tspan:: NTuple{2, Float64} ,h:: Float64 ,g:: Function ,alg:: LDEMSAlgHHL )
117+ sz, = size (g (1 ))
118+ i_mat = Matrix {Float64} (I, size (g (1 )))
119+ N_t = round (Int, (tspan[2 ] - tspan[1 ])/ h + 1 ) # number of time steps
120+ N = nextpow (2 ,2 * N_t + 1 ) # To ensure we have a power of 2 dimension for matrix
121+ A_ = zeros (ComplexF64, N* sz, N* sz)
122+ # Generates First two rows
123+ @inbounds A_[1 : sz, 1 : sz] = i_mat
124+ @inbounds A_[sz + 1 : 2 * sz, 1 : sz] = - 1 * (i_mat + h* g (tspan[1 ]))
125+ @inbounds A_[sz + 1 : 2 * sz,sz+ 1 : sz* 2 ] = i_mat
126+ # Generates additional rows based on k - step
127+ for i in 3 : alg. step
128+ @inbounds A_[sz* (i - 1 ) + 1 : sz* i, sz* (i - 3 ) + 1 : sz* i] = aval (QuAB2 (),(i- 2 )* h + tspan[1 ],h,g)
129+ end
130+ for i in alg. step + 1 : N_t
131+ @inbounds A_[sz* (i - 1 ) + 1 : sz* (i), sz* (i - alg. step - 1 ) + 1 : sz* i] = aval (alg,(i - 2 )* h + tspan[1 ],h,g)
132+ end
133+ # Generates half mirroring matrix
134+ for i in N_t + 1 : N
135+ @inbounds A_[sz* (i - 1 ) + 1 : sz* (i), sz* (i - 2 ) + 1 : sz* (i - 1 )] = - 1 * i_mat
136+ @inbounds A_[sz* (i - 1 ) + 1 : sz* (i), sz* (i - 1 ) + 1 : sz* i] = i_mat
137+ end
138+ A_ = [zero (A_) A_;A_' zero (A_)]
139+ return A_
86140end
141+
142+ function DiffEqBase. solve (prob:: QuLDEMSProblem{F,C,U,T} , alg:: LDEMSAlgHHL , dt = (prob. tspan[2 ]- prob. tspan[1 ])/ 100 , n_reg:: Int = 12 ) where {F,C,U,T}
143+ A = prob. A
144+ b = prob. b
145+ tspan = prob. tspan
146+ x = prob. u0
147+
148+ mat = array_qudiff (tspan, dt, A, alg)
149+ state = prepare_init_state (tspan, x, dt, b, alg)
150+ λ = maximum (eigvals (mat))
151+ C_value = minimum (eigvals (mat) .| > abs)* 0.01 ;
152+ mat = 1 / (λ* 2 )* mat
153+ state = state* 1 / (2 * λ) |> normalize!
154+ res = hhlsolve (mat,state, n_reg, C_value)
155+ res = res/ λ
156+ return res
157+ end ;
0 commit comments