|
1 | 1 | # Fetch packages.
|
2 | 2 | using Catalyst, NonlinearSolve, OrdinaryDiffEq, Statistics, SteadyStateDiffEq, StochasticDiffEq, Test
|
3 |
| -using ModelingToolkit: getdefault |
| 3 | +using ModelingToolkit: getdefault, getdescription, getdefault |
4 | 4 | using Symbolics: BasicSymbolic, unwrap
|
5 | 5 |
|
6 | 6 | # Sets stable rng number.
|
|
540 | 540 |
|
541 | 541 | ### DSL Tests ###
|
542 | 542 |
|
| 543 | +# Check that a hybrid CRN/DAE created programmatically and via the DSL are identical. |
| 544 | +# Checks where variables are implied from differential equations, and with variables/parameter |
| 545 | +# default values, types, and metadata. |
| 546 | +# Checks that generated system contents are correct, and ODE simulations are identical. |
| 547 | +let |
| 548 | + # Creates the model programmatically. |
| 549 | + @species X1(t) X2(t) X3(t) X_tot(t) |
| 550 | + @variables V(t)=5.0 [description="Volume"] N(t) X_conc(t) |
| 551 | + @parameters p k1 k2 d v n x_scale::Float32 |
| 552 | + eqs = [ |
| 553 | + Reaction(p, nothing, [X1]) |
| 554 | + Reaction(k1, [X1], [X2]) |
| 555 | + Reaction(k2, [X2], [X3]) |
| 556 | + Reaction(d, [X3], nothing) |
| 557 | + D(V) ~ X3/(1+X3) - v*V |
| 558 | + D(N) ~ - n*N*X3 |
| 559 | + V*X_conc ~ x_scale*(X1 + X2 + X3) |
| 560 | + X_tot + X1 + X2 ~ -X3 |
| 561 | + ] |
| 562 | + rs_prog = complete(ReactionSystem(eqs, t; name = :hybrid_rs)) |
| 563 | + |
| 564 | + # Creates the model via the DSL. |
| 565 | + rs_dsl = @reaction_network hybrid_rs begin |
| 566 | + @species X_tot(t) |
| 567 | + @variables X_conc(t) V(t)=5.0 [description="Volume"] |
| 568 | + @parameters v n x_scale::Float32 |
| 569 | + @equations begin |
| 570 | + D(V) ~ X3/(1+X3) - v*V |
| 571 | + D(N) ~ - n*N*X3 |
| 572 | + V*X_conc ~ x_scale*(X1 + X2 + X3) |
| 573 | + X_tot + X1 + X2 ~ -X3 |
| 574 | + end |
| 575 | + p, 0 --> X1 |
| 576 | + k1, X1 --> X2 |
| 577 | + k2, X2 --> X3 |
| 578 | + d, X3 --> 0 |
| 579 | + end |
| 580 | + |
| 581 | + # Checks that models are identical. Also checks that they have the correct content. |
| 582 | + @test rs_prog == rs_dsl |
| 583 | + |
| 584 | + @test issetequal(parameters(rs_dsl), [p, k1, k2, d, v, n, x_scale]) |
| 585 | + @test issetequal(species(rs_dsl), unknowns(rs_dsl)[1:4]) |
| 586 | + @test issetequal(unknowns(rs_dsl)[1:4], [X1, X2, X3, X_tot]) |
| 587 | + @test issetequal(unknowns(rs_dsl)[5:7], [V N X_conc]) |
| 588 | + @test issetequal(reactions(rs_dsl), equations(rs_dsl)[1:4]) |
| 589 | + @test issetequal(equations(rs_dsl)[1:4], eqs[1:4]) |
| 590 | + @test issetequal(equations(rs_dsl)[5:7], eqs[5:7]) |
| 591 | + |
| 592 | + @test getdescription(rs_dsl.V) == "Volume" |
| 593 | + @test getdefault(rs_dsl.V) == 5.0 |
| 594 | + @test unwrap(rs_dsl.x_scale) isa BasicSymbolic{Float32} |
| 595 | + |
| 596 | + # Checks that the models can be simulated and yield identical results. |
| 597 | + # Test most likely redundant, but seem useful to have one test like this to be sure. |
| 598 | + u0 = [X1 => 0.1, X2 => 0.2, X3 => 0.2, X_tot => 0.6, N => 10.0, X_conc => 10.0] |
| 599 | + tspan = (0.0, 10.0) |
| 600 | + ps = [p => 1.0, k1 => 1.2, k2 => 1.5, d => 2.0, v => 0.2, n => 0.5, x_scale => 2.0] |
| 601 | + |
| 602 | + @test_broken begin # ODEs become overdetermined. |
| 603 | + oprob_prog = ODEProblem(rs_prog, u0, tspan, ps; structural_simplify = true) |
| 604 | + oprob_dsl = ODEProblem(rs_dsl, u0, tspan, ps; structural_simplify = true) |
| 605 | + @test solve(oprob_prog, Tsit5()) == solve(oprob_dsl, Tsit5()) |
| 606 | + end |
| 607 | +end |
543 | 608 | ### Error Tests ###
|
544 | 609 |
|
545 | 610 | # Checks that various erroneous hybrid system declarations yield errors.
|
|
0 commit comments