(intro)= # An Introductory Example Solverz aims to help you model and solve your equations more efficiently. Say, we want to know how long it takes for an apple to fall from a tree to the ground. We have the differential equations ```{math} \left\{ \begin{aligned} &v'=-9.8\\ &h'=v \end{aligned} \right. ``` with $v(0)=20$ and $h(0)=0$, we can just type the codes ```python import matplotlib.pyplot as plt import numpy as np from Solverz import Model, Var, Ode, Opt, made_numerical, Rodas # Declare a simulation model m = Model() # Declare variables and equations m.h = Var('h', 0) m.v = Var('v', 20) m.f1 = Ode('f1', f=m.v, diff_var=m.h) m.f2 = Ode('f2', f=-9.8, diff_var=m.v) # Create the symbolic equation instance and the variable combination bball, y0 = m.create_instance() # Transform symbolic equations to python numerical functions. nbball = made_numerical(bball, y0, sparse=True) # Define events, that is, if the apple hits the ground then the simulation will cease. def events(t, y): value = np.array([y[0]]) isterminal = np.array([1]) direction = np.array([-1]) return value, isterminal, direction # Solve the DAE sol = Rodas(nbball, np.linspace(0, 30, 100), y0, Opt(event=events)) # Visualize plt.plot(sol.T, sol.Y['h'][:, 0]) plt.xlabel('Time/s') plt.ylabel('h/m') plt.show() ``` Then we have ![image.png](/pics/res.png) The model is solved with the stiffly accurate Rosenbrock type method, but you can also write your own solvers by the generated numerical interfaces. For example, the [multidimensional Newton method](https://en.wikipedia.org/wiki/Newton%27s_method) of AEs is a scheme with formulae ```{math} y_{k+1} = y_k - J_F(y_k)^{-1}F(y_k)\quad k=0,1,2,\cdots. ``` Its implementation using Solverz can be as simple as ```python # main loop while max(abs(df)) > tol: ite = ite + 1 y = y - solve(eqn.J(y, p), df) df = eqn.F(y, p) if ite >= 100: print(f"Cannot converge within 100 iterations. Deviation: {max(abs(df))}!") break ``` The numerical AE object `eqn` provides the $F(t,y,p)$ interface and its Jacobian $J(t,y,p)$, which grants your full flexibility. So that the implementation of the NR solver just resembles the formulae above. Sometimes you have very complex models and you dont want to re-derive them everytime. With Solverz, you can just use ```python from Solverz import module_printer pyprinter = module_printer(bball, y0, 'bounceball', jit=True) pyprinter.render() ``` to generate an independent python module of your simulation models. You can import them to your .py file by ```python from bounceball import mdl as nbball, y as y0 ```