/**
 * cont_sim.h
 * @brief motion of a single particle in a homogenous magnetic field simulator 
 * @author Michael Roth <xrothm00@stud.fit.vutbr.cz>
 * @version 1.0.5
 * @since 0.1
*/

// header guard
#ifndef CONT_SIM_H
#define CONT_SIM_H

// macros to specify the simulation parameters
#define N_INTEGRATORS 6
#define N_DETECTOR_PLANES 8

#define STEP_SIZE 0.05 // time step size of simulation [s]

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

// macro for the maximum deviation to consider tow floating points equal
#define MIN_STEP 0.000000000000001 // should equal 1 fs
#define PRECISION 1000 // 1024 might be better for precision

// macros for indexing the position vector within the state array
#define I_X 1
#define I_Y 3
#define I_Z 5

// macros for indexing the velocity vector within the state array 
#define I_VX 0
#define I_VY 2
#define I_VZ 4

// macros for the magnetic field vector
// this should be (re)defined in each simulation program 
// TODO rewrite in physics.h

#define B_X 0.0
#define B_Y 0.0
#define B_Z 1.0

/**
 * structure type Particle
 * @brief structure containing all information needed for continuos part of simulation
 *
 * @param id identification number of the particle
 * @param time current simulation time of the particle
 * @param end_time time of end of simulation for this particle
 * @param st[] state vector of this partice
 * @param m_0 rest mass of the particle
 * @param charge electromagnetic charge of the particle [C]
 * @param gamma relativistic speed factor used for mass and time corrections
 * @param gqm constant q / (m_0 / sqrt(1 - (v^2 / c^2)))
 * @author Michael Roth
 * @version 0.4
 * @since 0.3 
 */
typedef struct s_particle {
    int id;
    double time;
    double end_time;
    double st[N_INTEGRATORS];
    double m_0;
    double charge;
    double gamma;
    double gqm;
} Particle;

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

/**
 * function simulation_loop()
 * @brief function to run the simulation
 * @param p Particle structure to do the simulation on
 * @param default_step default step of the simulation
 * @param traj_f trajectory file to output to
 * @param log_f detector intersect file to output to
 * @param num_method numeric method callback to use
 * @author Michael Roth
 * @version 0.7
 * @since 0.1
 */
void simulation_loop(Particle p, 
                     double default_step, 
                     FILE *traj_f,
                     FILE *log_f, 
                     step_callback num_method);

/**
 * function state_condition()
 * @brief function to calculate if a state condition has changed
 * @param st current state of the particle
 * @param st_old old state of the particle
 * @author Michael Roth
 * @version 0.7
 * @since 0.5
 */
int state_condition(double st[], double st_old[]);

/**
 * function calculate_gqm()
 * @brief function to calculate the relativistic constants for the particle
 * @param p pointer to Particle structure 
 * @author Michael Roth
 * @version 0.4
 * @since 0.4
 */
void calculate_gqm(Particle * p);

/**
 * 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
 * @param gqm product of charge and mass
 * @author Michael Roth
 * @version 0.2
 * @since 0.1
 */
void dynamic(double st[], double in[], double gqm);

/**
 * function euler()
 * @brief calculates the next step of the continuous simulation using the Euler method
 * @param st[] state vector of the simulation
 * @param in[] integrator vector of the simulation
 * @param gqm product of charge and mass
 * @param step size of the time step of the algorithm
 * @author Michael Roth
 * @version 0.2
 * @since 0.1
 */
void euler(double st[], double gqm, double step);

/**
 * function rk4()
 * @brief calculates the next step of the continuous simulation using the 4th degree Runge-Kutta method
 * @param st[] state vector of the simulation
 * @param gqm product of charge and mass
 * @param step size of the time step of the algorithm
 * @author Michael Roth
 * @version 0.8
 * @since 0.1
 */
void rk4(double st[], double gqm, double step);

# endif // end of header guard