Simulation Dsolve/ParametricNDSolve

simulate[model,{t,tStart,tFinal}] can now use DSolve to get exact solutions to the system of ODEs. However, DSolve can take a long time to run for large models, so a 2 second timeout is incorporated.

simulate[model,{t,tStart,tFinal},parameterList] uses ParametricNDSolve to solve the ODEs leaving the parameters in parameterList as unknown. Simulating an incomplete model that is missing a few parameters will also return a parametric simulation, if the option "ParametricSolve"->True.

setSimulationParameters[simulation,{parameter->value},model] will substitute the values of the parameters into the parametric simulation.

Sample code to see DSolve in action:
`model1 = constructModel[{reaction["b1", {metabolite["x0", None]}, {metabolite["x1", None]}, {1, 1}, False]}, Parameters -> {rateconst["b1", True] -> 0.1 Hour^-1}, InitialConditions -> {metabolite["x0", None] -> 1 Milli Mole/Liter, metabolite["x1", None] -> 5 Milli Mole/Liter}, UnitChecking -> True];`
`sim1 = simulate[model1, {t, 0, 10}]`

Sample code for parametric simulations:
`model2 = constructModel[{reaction[ "b1", {metabolite["x0", None]}, {metabolite["x1", None]}, {1, 1}, False]}, Parameters -> {}, InitialConditions -> {metabolite["x0", None] -> 1 Milli Mole/Liter, metabolite["x1", None] -> 5 Milli Mole/Liter}, UnitChecking -> True];`
`sim2 = simulate[model2, {t, 0, 10}, "ParametricSolve" -> True]`
`sim3 = simulate[model1, {t, 0, 10}, {rateconst["b1", True]}]`
`sim4 = setSimulationParameters[sim2, {rateconst["b1", True] -> 0.1 Hour^-1}, model2]`