@@ -185,6 +185,242 @@ function change_of_variables(
185185 return new_sys
186186end
187187
188+ """
189+ Generates the system of ODEs to find solution to FDEs.
190+
191+ Example:
192+
193+ ```julia
194+ @independent_variables t
195+ @variables x(t)
196+ D = Differential(t)
197+ tspan = (0., 1.)
198+
199+ α = 0.5
200+ eqs = (9*gamma(1 + α)/4) - (3*t^(4 - α/2)*gamma(5 + α/2)/gamma(5 - α/2))
201+ eqs += (gamma(9)*t^(8 - α)/gamma(9 - α)) + (3/2*t^(α/2)-t^4)^3 - x^(3/2)
202+ sys = fractional_to_ordinary(eqs, x, α, 10^-7, 1)
203+
204+ prob = ODEProblem(sys, [], tspan)
205+ sol = solve(prob, radau5(), abstol = 1e-10, reltol = 1e-10)
206+ ```
207+ """
208+ function fractional_to_ordinary (
209+ eqs, variables, alphas, epsilon, T;
210+ initials = 0 , additional_eqs = [], iv = only (@independent_variables t), matrix= false
211+ )
212+ D = Differential (iv)
213+ i = 0
214+ all_eqs = Equation[]
215+ all_def = Pair[]
216+
217+ function fto_helper (sub_eq, sub_var, α; initial= 0 )
218+ alpha_0 = α
219+
220+ if (α > 1 )
221+ coeff = 1 / (α - 1 )
222+ m = 2
223+ while (α - m > 0 )
224+ coeff /= α - m
225+ m += 1
226+ end
227+ alpha_0 = α - m + 1
228+ end
229+
230+ δ = (gamma (alpha_0+ 1 ) * epsilon)^ (1 / alpha_0)
231+ a = pi / 2 * (1 - (1 - alpha_0)/ ((2 - alpha_0) * log (epsilon^- 1 )))
232+ h = 2 * pi * a / log (1 + (2 / epsilon * (cos (a))^ (alpha_0 - 1 )))
233+
234+ x_sub = (gamma (2 - alpha_0) * epsilon)^ (1 / (1 - alpha_0))
235+ x_sup = - log (gamma (1 - alpha_0) * epsilon)
236+ M = floor (Int, log (x_sub / T) / h)
237+ N = ceil (Int, log (x_sup / δ) / h)
238+
239+ function c_i (index)
240+ h * sin (pi * alpha_0) / pi * exp ((1 - alpha_0)* h* index)
241+ end
242+
243+ function γ_i (index)
244+ exp (h * index)
245+ end
246+
247+ new_eqs = Equation[]
248+ def = Pair[]
249+
250+ if matrix
251+ new_z = Symbol (:ʐ , :_ , i)
252+ i += 1
253+ γs = diagm ([γ_i (index) for index in M: N- 1 ])
254+ cs = [c_i (index) for index in M: N- 1 ]
255+
256+ if (α < 1 )
257+ new_z = only (@variables $ new_z (iv)[1 : N- M])
258+ new_eq = D (new_z) ~ - γs* new_z .+ sub_eq
259+ rhs = dot (cs, new_z) + initial
260+ push! (def, new_z=> zeros (N- M))
261+ else
262+ new_z = only (@variables $ new_z (iv)[1 : N- M, 1 : m])
263+ new_eq = D (new_z) ~ - γs* new_z + hcat (fill (sub_eq, N- M, 1 ), collect (new_z[:, 1 : m- 1 ]* diagm (1 : m- 1 )))
264+ rhs = coeff* sum (cs[i]* new_z[i, m] for i in 1 : N- M)
265+ for (index, value) in enumerate (initial)
266+ rhs += value * iv^ (index - 1 ) / gamma (index)
267+ end
268+ push! (def, new_z=> zeros (N- M, m))
269+ end
270+ push! (new_eqs, new_eq)
271+ else
272+ if (α < 1 )
273+ rhs = initial
274+ for index in range (M, N- 1 ; step= 1 )
275+ new_z = Symbol (:ʐ , :_ , i)
276+ i += 1
277+ new_z = ModelingToolkit. unwrap (only (@variables $ new_z (iv)))
278+ new_eq = D (new_z) ~ sub_eq - γ_i (index)* new_z
279+ push! (new_eqs, new_eq)
280+ push! (def, new_z=> 0 )
281+ rhs += c_i (index)* new_z
282+ end
283+ else
284+ rhs = 0
285+ for (index, value) in enumerate (initial)
286+ rhs += value * iv^ (index - 1 ) / gamma (index)
287+ end
288+ for index in range (M, N- 1 ; step= 1 )
289+ new_z = Symbol (:ʐ , :_ , i)
290+ i += 1
291+ γ = γ_i (index)
292+ base = sub_eq
293+ for k in range (1 , m; step= 1 )
294+ new_z = Symbol (:ʐ , :_ , index- M, :_ , k)
295+ new_z = ModelingToolkit. unwrap (only (@variables $ new_z (iv)))
296+ new_eq = D (new_z) ~ base - γ* new_z
297+ base = k * new_z
298+ push! (new_eqs, new_eq)
299+ push! (def, new_z=> 0 )
300+ end
301+ rhs += coeff* c_i (index)* new_z
302+ end
303+ end
304+ end
305+ push! (new_eqs, sub_var ~ rhs)
306+ return (new_eqs, def)
307+ end
308+
309+ for (eq, cur_var, alpha, init) in zip (eqs, variables, alphas, initials)
310+ (new_eqs, def) = fto_helper (eq, cur_var, alpha; initial= init)
311+ append! (all_eqs, new_eqs)
312+ append! (all_def, def)
313+ end
314+ append! (all_eqs, additional_eqs)
315+ @named sys = System (all_eqs, iv; defaults= all_def)
316+ return mtkcompile (sys)
317+ end
318+
319+ """
320+ Generates the system of ODEs to find solution to FDEs.
321+
322+ Example:
323+
324+ ```julia
325+ @independent_variables t
326+ @variables x_0(t)
327+ D = Differential(t)
328+ tspan = (0., 5000.)
329+
330+ function expect(t)
331+ return sqrt(2) * sin(t + pi/4)
332+ end
333+
334+ sys = linear_fractional_to_ordinary([3, 2.5, 2, 1, .5, 0], [1, 1, 1, 4, 1, 4], 6*cos(t), 10^-5, 5000; initials=[1, 1, -1])
335+ prob = ODEProblem(sys, [], tspan)
336+ sol = solve(prob, radau5(), abstol = 1e-5, reltol = 1e-5)
337+ ```
338+ """
339+ function linear_fractional_to_ordinary (
340+ degrees, coeffs, rhs, epsilon, T;
341+ initials = 0 , symbol = :x , iv = only (@independent_variables t), matrix= false
342+ )
343+ previous = Symbol (symbol, :_ , 0 )
344+ previous = ModelingToolkit. unwrap (only (@variables $ previous (iv)))
345+ @variables x_0 (iv)
346+ D = Differential (iv)
347+ i = 0
348+ all_eqs = Equation[]
349+ all_def = Pair[]
350+
351+ function fto_helper (sub_eq, α)
352+ δ = (gamma (α+ 1 ) * epsilon)^ (1 / α)
353+ a = pi / 2 * (1 - (1 - α)/ ((2 - α) * log (epsilon^- 1 )))
354+ h = 2 * pi * a / log (1 + (2 / epsilon * (cos (a))^ (α - 1 )))
355+
356+ x_sub = (gamma (2 - α) * epsilon)^ (1 / (1 - α))
357+ x_sup = - log (gamma (1 - α) * epsilon)
358+ M = floor (Int, log (x_sub / T) / h)
359+ N = ceil (Int, log (x_sup / δ) / h)
360+
361+ function c_i (index)
362+ h * sin (pi * α) / pi * exp ((1 - α)* h* index)
363+ end
364+
365+ function γ_i (index)
366+ exp (h * index)
367+ end
368+
369+ new_eqs = Equation[]
370+ def = Pair[]
371+ if matrix
372+ new_z = Symbol (:ʐ , :_ , i)
373+ i += 1
374+ γs = diagm ([γ_i (index) for index in M: N- 1 ])
375+ cs = [c_i (index) for index in M: N- 1 ]
376+
377+ new_z = only (@variables $ new_z (iv)[1 : N- M])
378+ new_eq = D (new_z) ~ - γs* new_z .+ sub_eq
379+ sum = dot (cs, new_z)
380+ push! (def, new_z=> zeros (N- M))
381+ push! (new_eqs, new_eq)
382+ else
383+ sum = 0
384+ for index in range (M, N- 1 ; step= 1 )
385+ new_z = Symbol (:ʐ , :_ , i)
386+ i += 1
387+ new_z = ModelingToolkit. unwrap (only (@variables $ new_z (iv)))
388+ new_eq = D (new_z) ~ sub_eq - γ_i (index)* new_z
389+ push! (new_eqs, new_eq)
390+ push! (def, new_z=> 0 )
391+ sum += c_i (index)* new_z
392+ end
393+ end
394+ return (new_eqs, def, sum)
395+ end
396+
397+ for i in range (1 , ceil (Int, degrees[1 ]); step= 1 )
398+ new_x = Symbol (symbol, :_ , i)
399+ new_x = ModelingToolkit. unwrap (only (@variables $ new_x (iv)))
400+ push! (all_eqs, D (previous) ~ new_x)
401+ push! (all_def, previous => initials[i])
402+ previous = new_x
403+ end
404+
405+ new_rhs = - rhs
406+ for (degree, coeff) in zip (degrees, coeffs)
407+ rounded = ceil (Int, degree)
408+ new_x = Symbol (symbol, :_ , rounded)
409+ new_x = ModelingToolkit. unwrap (only (@variables $ new_x (iv)))
410+ if isinteger (degree)
411+ new_rhs += coeff * new_x
412+ else
413+ (new_eqs, def, sum) = fto_helper (new_x, rounded - degree)
414+ append! (all_eqs, new_eqs)
415+ append! (all_def, def)
416+ new_rhs += coeff * sum
417+ end
418+ end
419+ push! (all_eqs, 0 ~ new_rhs)
420+ @named sys = System (all_eqs, iv; defaults= all_def)
421+ return mtkcompile (sys)
422+ end
423+
188424"""
189425 change_independent_variable(
190426 sys::System, iv, eqs = [];
0 commit comments