Simframe: A Python Framework for Scientific Simulations

Conceptually, upon initialization Simframe is an empty frame that can be filled with Fields containing data. Fields are derived from numpy.ndarrays (Harris et al., 2020), but with extended functionality. The user can then specify differential equations to those data fields and can set up an integrator which is integrating those fields according the given differential equations. Therefore, Simframe can only work with data, that can be stored in NumPy arrays.

Conceptually, upon initialization Simframe is an empty frame that can be filled with Fields containing data. Fields are derived from numpy.ndarrays (Harris et al., 2020), but with extended functionality. The user can then specify differential equations to those data fields and can set up an integrator which is integrating those fields according the given differential equations. Therefore, Simframe can only work with data, that can be stored in NumPy arrays.
Data fields that should not be integrated themselves, but are still required for the model, can have an update function assigned to them, according to which they will be updated once per integration step.
Simframe contains a number of integration schemes of different orders, both for explicit and implicit integration. Furthermore, Simframe includes methods to read and write output files.
Due to its modular structure, Simframe can be extended at will, for example, by implementing new integration schemes and/or user-defined output formats.

Statement of need
Solving differential equations is part of the daily work of scientists. Simframe facilitates this by providing the infrastructure: Data structures, integration schemes, and methods to write and read output files.
On one hand, Simframe can be used to quickly solve small scientific problems, and, on the other hand, it can be easily extended to larger projects due to its versatility and modular structure.
Furthermore, Simframe is ideal for beginners without programming experience who are taking their first steps in solving differential equations. It can therefore be used to design lectures or practical courses at schools and universities, as it allows students to concentrate on the essentials without having to write larger programs on their own.
Plenty of ODE solver packages already exist for Python, like solve_ivp or odeint in Sc iPy's integrate module, however, these do not provide data structures, nor input/output capabilities. Simframe offers a flexible framework to define, group, and describe data, define how it is updated, use existing integrators or define new ones, and to handle writing of data or serializing the entire simulation object, all in one modular package. Existing integrators like solve_ivp or odeint can be used within Simframe by simply adding them to an integration scheme.

Data fields
The data fields of Simframe are subclassed NumPy ndarrays. The full NumPy functionality can therefore be used on Simframe data fields. The ndarrays have been extended to store additional information about differential equations or update functions and a string description of the field. The data fields can be arranged in groups to facilitate a clear structure within the data frame.

Integration schemes
Simframe includes a number of basic integration schemes by default (Hairer et al., 1993). All of the implemented schemes are Runge-Kutta methods of different orders. Some of the methods are adaptive, i.e., they are embedded Runge-Kutta methods, that return an optimal step size for the integration variable, such that the desired accuracy is achieved. The implicit methods require a matrix inversion that is either done directly by NumPy or by using the GMRES solver provided by SciPy .
Here is a list of all implemented integration schemes: Order Scheme solver

I/O
By default Simframe has two options for storing simulation results. One is by storing the data in a separate namespace within the Simframe object itself, useful for small simulations to access results without writing/reading data files. Another one is by storing the data in HDF5 data files using the h5py package (Collette, 2013).
If configured by the user, Simframe is writing dump files, from which the simulation can be resumed, in case the program crashed unexpectedly. These dump files are serialized Simframe objects using the dill package (McKerns et al., 2012).