@@ -185,6 +185,242 @@ function change_of_variables(
185
185
return new_sys
186
186
end
187
187
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
+
188
424
"""
189
425
change_independent_variable(
190
426
sys::System, iv, eqs = [];
0 commit comments