/**
 * model.h
 * @brief particle motion simulator
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 0.1
*/

// header guard
#ifndef MODEL_H
#define MODEL_H

// macros to alter simulation parameters
#define N_INTEGRATORS 9
#define N_DETECTOR_PLANES 8

// default time step size [s]
#define DEFAULT_STEP 1E-4
#define MIN_STEP 0.000000000001
#define PRECISION 1000 // TODO try 1024 to compare speed of implementation

// important physical constants
#define PI 3.14159265358979323846
#define LIGHT_SPEED 299792458 // [m/s]

// macros for state conditions
#define NO_CONDITION_TRIGGERED 0
#define CONDITION_TRIGGERED 1
#define CONDITION_EXACT 2

// NOTE: due to the new simulation model properties 
// are state conditions unnecessary

/* 
* state vector has five degrees of freedom:
* r = (x, y, t_x, t_y, q/p), where:
* t_x = tan(theta_x),
* t_y = tan(theta_y),
* q/p is the charge to inverse momentum ratio
*/ 

// macros for indexing the state vector
#define I_X 0 // x position
#define I_Y 1 // y position
#define I_TX 2 // dx/dz
#define I_TY 3 // dy/dz
#define I_QP 4 // q/p
#define I_TR 5 // sqrt(tx^2 + ty^2 + 1)
#define I_BX 6 // x field of the magnetic field
#define I_BY 7 // y field of the magnetic field
#define I_BZ 8 // z field of the magnetic field

// define the callback the integrator function will be using
typedef void (*step_callback)(double[], double);

/**
 * function simulation_loop()
 * @brief function running the simulation
 * @param st[] initialized state vector to run the simulation on
 * @param default_step default step of the simulation
 * @param z0 starting z position of the simulation
 * @param zmax ending z position of the simulation
 * @param traj_f trajectory output file descriptor
 * @param num_method numeric function to use
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 0.1
 */
void simulation_loop(double st[],
                     double default_step,
                     double z0,
                     double zmax,
                     FILE *traj_f,
                     step_callback num_method);

/**
 * function dynamic()
 * @brief updates the integrators in the dynamic part of simulation
 * @param st[] state vector of the simulation
 * @param in[] integrator vector of the simulation
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 0.1
 */
void dynamic(double st[], double in[]);

/**
 * function euler()
 * @brief calculates the next step of the simulation using the Euler method
 * @param st[] state vector of the simulation
 * @param in[] integrator vector of the simulation
 * @param step size of the z step
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 0.1
 */
void euler(double st[], double step);

/**
 * function rk4()
 * @brief calculates the next step of the simulation using the 4th order Runge-Kutta method
 * @param st[] state vector of the simulation
 * @param in[] integrator vector of the simulation
 * @param step size of the z-step
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 0.1
 */
void rk4(double st[], double step);

/**
 * function lorenz_factor()
 * @brief calculates the lorenz factor of particle given it's velocity
 * @param v speed of the particle in m/s
 * @return lorenz factor \gamma
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 2.0
 * @since 2.0
 */
double lorenz_factor(double v);

#endif // end of the header guard