/*!< \brief Trace magnetic field lines forward and backward from each DCCRG cell to record the connectivity and detect flux ropes.
    *
    * Full box connection and flux rope tracing
    *
    * We are doing two things in one function here as we save a *lot* especially in MPI reductions by combining those. And they are
    * doing very similar things anyway.
    *
    * Firstly we are interested in knowing the ultimate magnetic connection forward and backward from any given location. The
    * locations are the DCCRG cell centers, there's too many fsgrid cells for practical purposes.
    * We initially discard cells too close to the domain boundaries or inside the inner radius as type OUTSIDE.
    * Therefore we step along the magnetic field until we hit an outer box wall (OPEN) or the inner boundary
    * radius (CLOSED). In rare cases the line might not have reached either of these two termination conditions by the time the
    * field line has reached a length of maxTracingDistance. In that case we call it DANGLING, it likely ended up in a loop
    * somewhere (we don't call it "loop" to avoid confusion with the flux rope tracing). As long as we have not hit any of the above
    * termination conditions, the type is called UNPROCESSED. We allow fieldTracingParameters.fullbox_max_incomplete_cells to remain
    * UNPROCESSED when we exit the loop, that is a fraction of the total cells left over, as this allows substantial shortening of
    * the total time spent due to the MPI_Allreduce calls occurring when we cross MPI domain boundaries. (NOTE: an algorithm doing
    * direct task-to-task communication will likely be more efficient!) The connection type of the field line is a member of the
    * enum TracingLineEndType and stored in cellFWConnection, cellBWConnection, cellConnection and the reduction arrays.
    * enum TracingLineEndType {
    *    UNPROCESSED,
    *    CLOSED,
    *    OPEN,
    *    DANGLING,
    *    OUTSIDE,
    *    N_TYPES
    * };
    * Once we have obtained a connection type for both directions, we parse the combinations and assign a value in the enum
    * TracingPointConnectionType below to CellParams::CONNECTION that will be written out by the vg_connection DRO.
    * enum TracingPointConnectionType {
    *    CLOSED_CLOSED,
    *    CLOSED_OPEN,
    *    OPEN_CLOSED,
    *    OPEN_OPEN,
    *    CLOSED_DANGLING,
    *    DANGLING_CLOSED,
    *    OPEN_DANGLING,
    *    DANGLING_OPEN,
    *    DANGLING_DANGLING,
    *    INVALID
    * };
    *
    * Secondly, we are interested in finding out whether the seed point/DCCRG cell centre coordinate (again, too many fsgrid cells
    * for sanity) are near/in a flux rope. As this relies also on tracing forward and backward along the field, we piggyback on the
    * full box connection algorithm explained above.
    * We trace along the field up to fieldTracingParameters.fluxrope_max_curvature_radii_to_trace*cellCurvatureRadius[n] and if
    * within that tracing distance we have't extended further than
    * fieldTracingParameters.fluxrope_max_curvature_radii_extent*cellCurvatureRadius[n] we are rolled up tightly enough to consider
    * being close to a flux rope. We'll store the max extension reached into cellMaxExtension[n] for later fine-grained analysis.
    * The arithmetic idea to avoid using yet more arrays:
    * We use the cellFWConnection[n]/cellBWConnection[n]/cellConnection[n] (that can only be UNPROCESSED, CLOSED, OPEN or DANGLING,
    * see TracingLineEndType enum above, ending with N_TYPES). As long as no full box tracing termination condition was reached
    * we are at UNPROCESSED. If we exceed fieldTracingParameters.fluxrope_max_curvature_radii_to_trace*cellCurvatureRadius[n], we
    * definitely are not near a flux rope and we mark this by adding N_TYPES to cellConnection[n].
    * If we reach fieldTracingParameters.fluxrope_max_curvature_radii_to_trace*cellCurvatureRadius[n] without hitting the other
    * thresholds or the inner/outer domain limits we are near/at a flux rope and we mark this by adding 2*N_TYPES to
    * cellConnection[n].
    * Later in the tracing when we reach a full box tracing termination condition we add CLOSED, OPEN or DANGLING to
    * cellConnection[n]. If we reached such termination condition before the flux rope method reached a conclusion it's fine too,
    * nothing has been added to cellConnection[n].
    * At the very end, we check whether both cellFWConnection[n] and cellBWConnection[n] >= 2*TracingLineEndType::N_TYPES. If yes,
    * this cell is near a fluxrope. This means we store the value of cellMaxExtension[n] into CellParams::FLUXROPE. Otherwise we
    * store zero.
    * After that we apply % TracingLineEndType::N_TYPES to recover values UNPROCESSED, CLOSED, OPEN, DANGLING, OUTSIDE in
    * cellFWConnection[n] and cellBWConnection[n] so that we can assign the connection types for the full box connection described
    * above.
    *
    * As a freebie since we computed the curvature anyway for flux rope tracing we store that into CellParams::CURVATUREX/Y/Z.
    *
    * \sa stepCellAcrossTaskDomain
    */


/*
  Compute parabolic reconstruction with an explicit scheme
*/


/*!
  Compute left face value based on the explicit h8 estimate.

  Right face value can be obtained as left face value of cell i + 1.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face is computed
  \param fv_l Face value on left face of cell i
*/


/*!
  Compute left face derivative based on the explicit h7 estimate.

  Right face derivative can be obtained as left face derivative of cell i + 1.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face derivativeis computed
  \param fd_l Face derivative on left face of cell i
*/


/*!
  Compute left face value based on the explicit h6 estimate.

  Right face value can be obtained as left face value of cell i + 1.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face is computed
  \param fv_l Face value on left face of cell i
*/


/*!
  Compute left face derivative based on the explicit h5 estimate.

  Right face derivative can be obtained as left face derivative of cell i + 1.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face derivativeis computed
  \param fd_l Face derivative on left face of cell i
*/


/*!
  Compute left and right face value based on the explicit h5 estimate.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face is computed
  \param fv_l Face value on left face of cell i
*/


/*!
  Compute left face value based on the explicit h4 estimate.

  Right face value can be obtained as left face value of cell i + 1.

  \param values Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face is computed
  \param fv_l Face value on left face of cell i
*/


/*!

  Compute left face value based on the explicit h4 estimate for nonuniform grid.
  Eqn 45 in White et. al. 2008

  \param u Array with volume averages. It is assumed a large enough stencil is defined around i.
  \param i Index of cell in values for which the left face is computed
  \param fv_l Face value on left face of cell i
  \param h Array with cell widths. Can be in abritrary units since they always cancel. Maybe 1/refinement ratio?
*/


/*Filters in section 2.6.1 of white et al. to be used for PQM
  1) Checks for extrema and flattens them
  2) Makes face values bounded
  3) Makes sure face slopes are consistent with PLM slope
*/


/*Filters in section 2.6.1 of white et al. to be used for PPM
  1) Checks for extrema and flattens them
  2) Makes face values bounded
  3) Makes sure face slopes are consistent with PLM slope
*/


/* Get cellIDs for spatial cells that are considered target / source cells for a pencil.
 *
 * Source cells are cells that the pencil reads data from to compute polynomial
 * fits that are used for propagation in the vlasov solver. All cells included
 * in the pencil proper + VLASOV_STENCIL_WIDTH cells on both ends are source cells.
 * Invalid cells are replaced by closest good cells.
 * Boundary cells are included.
 *
 * Target cells are cells that the pencil writes data into after translation by
 * the vlasov solver. All cells included in the pencil proper + 1 cells on both ends
 * are target cells.
 *
 * There is only one list of cellIDs for the pencil, where each source cell has also
 * their width stored, and for target cells, the relative contribution is stored. If
 * the cell in question is not a target cell, the contribution is set to zero.
 *
 * @param [in] mpiGrid DCCRG grid object
 * @param [inout] ids pointer to subsection of vector of ids for actual pencil
 * @param [in] L length of pencil (including stencil cells)
 * @param [in] dimension spatial dimension
 * @param [in] path index of the desired face neighbor when going to a higher refinement level
 * @param [out] source pointer to subsection of vector storing cell widths
 * @param [out] targetRatios pointer to subsection of vector storing relative contribution of pencil to target cells
 */


/* Select one nearest neighbor of a cell on the + side in a given dimension. If the neighbor
 * has a higher level of refinement, a path variable is needed to make the selection.
 * Returns INVALID_CELLID if the nearest neighbor is not local to this process.
 *
 * @param grid DCCRG grid object
 * @param id DCCRG cell id
 * @param dimension spatial dimension
 * @param path index of the desired face neighbor
 * @return neighbor DCCRG cell id of the neighbor
 */


/* Recursive function for building one-dimensional pencils to cover local DCCRG cells.
 * Starts from a given seedID and proceeds finding the nearest neighbor in the given dimension
 * and adding it to the pencil until no neighbors are found or an endId is met. When a higher
 * refinement level (ie. multiple nearest neighbors) is met, the pencil splits into four
 * copies to remain at a width of 1 cell. This is done by the function calling itself recursively
 * and passing as inputs the cells added so far. The cell selected by each copy of the function
 * at a split is stored in the path variable, the same path has to be followed if a refinement
 * level is encoutered multiple times.
 *
 * @param [in] grid DCCRG grid object
 * @param [out] pencils Pencil data struct
 * @param [in] seedId DCCRG cell id where we start building the pencil.
 *             The pencil will continue in the + direction in the given dimension until an end condition is met
 * @param [in] dimension Spatial dimension
 * @param [in] path Integer value that determines which neighbor is added to the pencil when a higher refinement level is met
 * @param [in] endIds Prescribed end conditions for the pencil. If any of these cell ids is about to be added to the pencil,
 *             the builder terminates.
 */


/* Check whether the ghost cells around the pencil contain higher refinement than the pencil does.
 * If they do, the pencil must be split to match the finest refined ghost cell.
 *
 * @param mpiGrid DCCRG grid object
 * @param pencils Pencil data struct
 * @param dimension Spatial dimension
 */


/* Checks that each local spatial cell appears in pencils at least 1 time.
 *
 * @param mpiGrid DCCRG grid object
 * @param cells Local spatial cells
 * @param pencils Pencil data struct
 */


/* Debugging function, prints the list of cells in each pencil
 *
 * @param pencils Pencil data struct
 * @param dimension Spatial dimension
 * @param myRank MPI rank
 */


/* Wrapper function for calling seed ID selection and pencil generation, for all dimensions.
 * Includes threading and gathering of pencils into thread-containers.
 *
 * @param [in] mpiGrid DCCRG grid object
 */


/* Wrapper function for calling seed ID selection and pencil generation, per dimension.
 * Includes threading and gathering of pencils into thread-containers.
 *
 * @param [in] mpiGrid DCCRG grid object
 * @param [in] dimension Spatial dimension
 */


// Split one pencil into up to four pencils covering the same space.
// dx and dy are the dimensions of the original pencil.


/** Attempt to add the given velocity block to the given velocity mesh.
 * If the block was added to the mesh, its data is set to zero values and
 * velocity block parameters are calculated.
 * @param blockGID Global ID of the added velocity block.
 * @param vmesh Velocity mesh where the block is added.
 * @param blockContainer Velocity block data container.
 * @return Local ID of the added block. If the block was not added, the
 * local ID of the null velocity block is returned instead.*/


/** Accelerate the given population to new time t+dt.
 * This function is AMR safe.
 * @param popID Particle population ID.
 * @param globalMaxSubcycles Number of times acceleration is subcycled.
 * @param step The current subcycle step.
 * @param mpiGrid Parallel grid library.
 * @param propagatedCells List of cells in which the population is accelerated.
 * @param dt Timestep.*/


/** Accelerate all particle populations to new time t+dt.
 * This function is AMR safe.
 * @param mpiGrid Parallel grid library.
 * @param dt Time step.*/


/*make sure quartic polynomial is monotonic*/


/*!
  Compute max timestep for vlasov acceleration for the particular population
  in one spatial cell.

 * @param spatial_cell Spatial cell containing the accelerated population.
 * @param popID ID of the accelerated particle species.
*/


/*!
 Compute transform during on timestep, and update the bulk velocity of the
 cell
 * @param spatial_cell Spatial cell containing the accelerated population.
 * @param popID ID of the accelerated particle species.
 * @param dt Time step of one subcycle.
*/


/*!
 Compute PLM coefficients
 f(v) = a[0] + a[1]/2.0*t
t=(v-v_{i-0.5})/dv where v_{i-0.5} is the left face of a cell
The factor 2.0 is in the polynom to ease integration, then integral is a[0]*t + a[1]*t**2
*/


/** Calculate zeroth, first, and (possibly) second bulk velocity moments for the
 * given spatial cell. The calculated moments include contributions from
 * all existing particle populations. This function is VAMR safe.
 * @param cell Spatial cell.
 * @param computeSecond If true, second velocity moments are calculated.
 * @param computePopulationMomentsOnly Do not update the combined moments in CellParams if true
 * @param doNotSkip If false, DO_NOT_COMPUTE cells are skipped.*/


/** Calculate zeroth, first, and (possibly) second bulk velocity moments for the
 * given spatial cell. The calculated moments include
 * contributions from all existing particle populations. The calculated moments
 * are stored to SpatialCell::parameters in _R variables. This function is VAMR safe.
 * @param mpiGrid Parallel grid library.
 * @param cells Vector containing the spatial cells to be calculated.
 * @param computeSecond If true, second velocity moments are calculated.*/


/** Calculate zeroth, first, and (possibly) second bulk velocity moments for the
 * given spatial cell. Additionally, for each species, calculate the maximum
 * spatial time step so that CFL(spatial)=1. The calculated moments include
 * contributions from all existing particle populations. The calculated moments
 * are stored to SpatialCell::parameters in _V variables. This function is VAMR safe.
 * @param mpiGrid Parallel grid library.
 * @param cells Vector containing the spatial cells to be calculated.
 * @param computeSecond If true, second velocity moments are calculated.*/


/* Propagate a given velocity block in all spatial cells of a pencil by a time step dt using a PPM reconstruction.
 *
 * @param dz Width of spatial cells in the direction of the pencil, vector datatype
 * @param values Density values of the block, vector datatype
 * @param dimension Satial dimension
 * @param blockGID Global ID of the velocity block.
 * @param dt Time step
 * @param vmesh Velocity mesh object
 * @param lengthOfPencil Number of cells in the pencil
 */


/* Copy the pencil source data to the temporary values array, so that the
 * dimensions are correctly swapped.
 *
 * This function must be thread-safe.
 *
 * @param blockDataPointer Vector of pre-prepared pointers to input (cell) block data
 * @param start Index from blockDataPointer to start at
 * @param int lengthOfPencil Number of spatial cells in pencil (not inclusive 2*VLASOV_STENCIL_WIDTH
 * @param values Vector into which the data should be loaded
 * @param cellid_transpose
 * @param popID ID of the particle species.
 */


/* Map velocity blocks in all local cells forward by one time step in one spatial dimension.
 * This function uses 1-cell wide pencils to update cells in-place to avoid allocating large
 * temporary buffers.
 *
 * @param [in] mpiGrid DCCRG grid object
 * @param [in] localPropagatedCells List of local cells that get propagated
 * ie. not boundary or DO_NOT_COMPUTE
 * @param [in] remoteTargetCells List of non-local target cells
 * @param [in] dimension Spatial dimension
 * @param [in] dt Time step
 * @param [in] popId Particle population ID
 */


/* This function communicates the mapping on process boundaries, and then updates the data to their correct values.
 * When sending data between neighbors of different refinement levels, special care has to be taken to ensure that
 * The sending and receiving ranks allocate the correct size arrays for neighbor_block_data.
 * This is partially due to DCCRG defining neighborhood size relative to the host cell. For details, see
 * https://github.com/fmihpc/dccrg/issues/12
 *
 * @param mpiGrid DCCRG grid object
 * @param dimension Spatial dimension
 * @param direction Direction of communication (+ or -)
 * @param popId Particle population ID
 */


/**
  Computes the intersection point of a plane and a line

  \param l_point Point on the line
  \param l_direction Vector in the direction of the line
  \param p_point Point on plane
  \param p_normal Normal vector to plane
  \param intersection The function will set this to the intersection point.*/


/*!
Computes the first intersection data; this is z~ in section 2.4 in Zerroukat et al (2012). We assume all velocity cells have the same dimensions.
Intersection z coordinate for (i,j,k) is: intersection + i * intersection_di + j * intersection_dj + k * intersection_dk
\param spatial_cell spatial cell that is accelerated
\param fwd_transform Transform that describes acceleration forward in time
\param bwd_transform Transform that describes acceleration backward in time, used to compute the lagrangian departure gri
\param dimension Along which dimension is this intersection/mapping computation done. It is assumed the three mappings are in order 012, 120 or 201
\param refLevel Refinement level at which intersections are computed
\param intersection Intersection z coordinate at i,j,k=0
\param intersection_di Change in z-coordinate for a change in i index of 1
\param intersection_dj Change in z-coordinate for a change in j index of 1
\param intersection_dk Change in z-coordinate for a change in k index of 1 */


/*!
  Computes the second intersection data; this is x~ in section 2.4 in Zerroukat et al (2012). We assume all velocity cells have the same dimensions.
  Intersection x coordinate for (i,j,k) is: intersection + i * intersection_di + j * intersection_dj + k * intersection_dk
  \param spatial_cell spatial cell that is accelerated
  \param fwd_transform Transform that describes acceleration forward in time
  \param bwd_transform Transform that describes acceleration backward in time, used to compute the lagrangian departure grid
  \param dimension Along which dimension is this intersection/mapping computation done. It is assumed the three mappings are in order 012, 120 or 201
  \param refLevel Refinement level at which the intersections are computed
  \param intersection Intersection x-coordinate at i,j,k=0
  \param intersection_di Change in x-coordinate for a change in i index of 1
  \param intersection_dj Change in x-coordinate for a change in j index of 1
  \param intersection_dk Change in x-coordinate for a change in k index of 1*/


/*!
  Computes the third intersection data; this is y intersections in Zerroukat et al (2012). We assume all velocity cells have the same dimensions.
  Intersection y-coordinate for (i,j,k) is: intersection + i * intersection_di + j * intersection_dj + k * intersection_dk
  \param spatial_cell spatial cell that is accelerated
  \param fwd_transform Transform that describes acceleration forward in time
  \param bwd_transform Transform that describes acceleration backward in time, used to compute the lagrangian departure grid
  \param dimension Along which dimension is this intersection/mapping computation done. It is assumed the three mappings are in order 012, 120 or 201
  \param refLevel Refinement level at which intersections are computed
  \param intersection Intersection y-coordinate at i,j,k=0
  \param intersection_di Change in y-coordinate for a change in i index of 1
  \param intersection_dj Change in y-coordinate for a change in j index of 1
  \param intersection_dk Change in y-coordinate for a change in k index of 1

  euclidian y goes from vy_min to vy_max, this is mapped to wherever y plane is in lagrangian.*/


/*compute spatial neighbors for source stencil with a size of 2*
 * VLASOV_STENCIL_WIDTH + 1, cellID at VLASOV_STENCIL_WIDTH. First
 * bondary layer included. Invalid cells are replaced by closest good
 * cells (i.e. boundary condition uses constant extrapolation for the
 * stencil values at boundaries*/


/* Copy the data to the temporary values array, so that the
 * dimensions are correctly swapped. Also, copy the same block for
 * then neighboring spatial cells (in the dimension). neighbors
 * generated with compute_spatial_neighbors_wboundcond).
 *
 * This function must be thread-safe.
 *
 * @param source_neighbors Array containing the VLASOV_STENCIL_WIDTH closest
 * spatial neighbors of this cell in the propagated dimension.
 * @param blockGID Global ID of the velocity block.
 * @param values Vector where loaded data is stored.
 * @param cellid_transpose
 * @param popID ID of the particle species.
 */


/*
   Here we map from the current time step grid, to a target grid which
   is the lagrangian departure grid (so th grid at timestep +dt,
   tracked backwards by -dt). This is done in ordinary space in the translation step

   This function can, and should be, safely called in a parallel
   OpenMP region (as long as it does only one dimension per parallel
   refion). It is safe as each thread only computes certain blocks (blockID%tnum_threads = thread_num */


/*!

  This function communicates the mapping on process boundaries, and then updates the data to their correct values.
  TODO, this could be inside an openmp region, in which case some m ore barriers and masters should be added

  \par dimension: 0,1,2 for x,y,z
  \par direction: 1 for + dir, -1 for - dir
*/


/*!
  Superbee slope limiter
*/


/*!
  Minmod slope limiter
*/


/* Slope limiter with abs and sign separatelym, uses the currently active slope limiter*/


/*!
  Prepare to accelerate species in cell. Sets the maximum allowed dt to the
  correct value.

 * @param spatial_cell Spatial cell containing the accelerated population.
 * @param popID ID of the accelerated particle species.
*/


/*
Filter moments after feeding them to FsGrid to alleviate the staircase effect caused in AMR runs.
This is using a 3D, 5-point stencil triangle kernel.
*/


/*
Map from dccrg cell id to fsgrid global cell ids when they aren't identical (ie. when dccrg has refinement).
*/


/** Calculate the electron pressure gradient term on all given cells.
 * @param sysBoundaries System boundary condition functions.
 */


/*! Re-initialize field propagator after rebalance. E, BGB, RHO, RHO_V,
 cell_dimensions, sysboundaryflag need to be up to date for the
 extended neighborhood
 */


/*! \brief Top-level field propagation function.
 *
 * Propagates the magnetic field, computes the derivatives and the upwinded
 * electric field, then computes the volume-averaged field values. Takes care
 * of the Runge-Kutta iteration at the top level, the functions called get as
 * an argument the element from the enum defining the current stage and handle
 * their job correspondingly.
 *
 * \param dt Length of the time step
 * \param subcycles Number of subcycles to compute.
 *
 * \sa propagateMagneticFieldSimple calculateDerivativesSimple calculateUpwindedElectricFieldSimple calculateVolumeAveragedFields calculateBVOLDerivativesSimple
 *
 */


/*! \brief Low-level helper function.
 *
 * Computes the correct combination of speeds to determine the CFL limits.
 *
 * It should be in-plane, but we use the complete wave speeds from calculateWaveSpeed??().
 *
 * At the moment it computes the geometric mean of both bulk velocity components
 * and takes the maximum of that plus either the magnetosonic or the whistler speed.
 *
 * \sa calculateWaveSpeedYZ calculateWaveSpeedXY calculateWaveSpeedZX
 *
 * \param v0 Flow in first direction
 * \param v1 Flow in second direction
 * \param vA Alfven speed
 * \param vS Sound speed
 * \param vW Whistler speed
 */


/*! \brief Low-level helper function.
 *
 * Computes the magnetosonic speed in the YZ plane. Used in upwinding the electric field X component,
 * at the interface between cell (i,j,k) and (nbi,nbj,nbk).
 *
 * Expects that the correct RHO and B fields are being passed, depending on the
 * stage of the Runge-Kutta time stepping method.
 *
 * If fields are not propagated, returns 0.0 as there is no information propagating.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param nbi,nbj,nbk fsGrid cell coordinates for the adjacent cell
 * \param By Current cell's By
 * \param Bz Current cell's Bz
 * \param dBydx dBydx derivative
 * \param dBydz dBydz derivative
 * \param dBzdx dBzdx derivative
 * \param dBzdy dBzdy derivative
 * \param ydir +1 or -1 depending on the interpolation direction in y
 * \param zdir +1 or -1 depending on the interpolation direction in z
 * \param minRhom Minimum mass density allowed from the neighborhood
 * \param maxRhom Maximum mass density allowed from the neighborhood
 * \param ret_vA Alfven speed returned
 * \param ret_vS Sound speed returned
 * \param ret_vW Whistler speed returned
 */


/*! \brief Low-level helper function.
 *
 * Computes the magnetosonic speed in the XZ plane. Used in upwinding the electric field Y component,
 * at the interface between cell (i,j,k) and (nbi,nbj,nbk).
 *
 * Expects that the correct RHO and B fields are being passed, depending on the stage of the Runge-Kutta time stepping method.
 *
 * If fields are not propagated, returns 0.0 as there is no information propagating.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param nbi,nbj,nbk fsGrid cell coordinates for the adjacent cell
 * \param Bx Current cell's Bx
 * \param Bz Current cell's Bz
 * \param dBxdy dBxdy derivative
 * \param dBxdz dBxdz derivative
 * \param dBzdx dBzdx derivative
 * \param dBzdy dBzdy derivative
 * \param xdir +1 or -1 depending on the interpolation direction in x
 * \param zdir +1 or -1 depending on the interpolation direction in z
 * \param minRhom Minimum mass density allowed from the neighborhood
 * \param maxRhom Maximum mass density allowed from the neighborhood
 * \param ret_vA Alfven speed returned
 * \param ret_vS Sound speed returned
 * \param ret_vW Whistler speed returned
 */


/*! \brief Low-level helper function.
 *
 * Computes the magnetosonic speed in the XY plane. Used in upwinding the electric field Z component,
 * at the interface between cell (i,j,k) and (nbi,nbj,nbk).
 *
 * Expects that the correct RHO and B fields are being passed, depending on the stage of the Runge-Kutta time stepping method.
 *
 * If fields are not propagated, returns 0.0 as there is no information propagating.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param nbi,nbj,nbk fsGrid cell coordinates for the adjacent cell
 * \param Bx Current cell's Bx
 * \param By Current cell's By
 * \param dBxdy dBxdy derivative
 * \param dBxdz dBxdz derivative
 * \param dBydx dBydx derivative
 * \param dBydz dBydz derivative
 * \param xdir +1 or -1 depending on the interpolation direction in x
 * \param ydir +1 or -1 depending on the interpolation direction in y
 * \param minRhom Minimum mass density allowed from the neighborhood
 * \param maxRhom Maximum mass density allowed from the neighborhood
 * \param ret_vA Alfven speed returned
 * \param ret_vS Sound speed returned
 * \param ret_vW Whistler speed returned
 */


/*! \brief Low-level electric field propagation function.
 *
 * Computes the upwinded electric field X component along the cell's corresponding edge as the cross product of B and V in the YZ plane. Also includes the calculation of the maximally allowed time step.
 *
 * Expects that the correct RHO and B fields are being passed, depending on the stage of the Runge-Kutta time stepping method.
 *
 * Note that the background B field is excluded from the diffusive term calculations because they are equivalent to a current term and the background field is curl-free.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EGrid fsGrid holding the electric field
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param EGradPeGrid fsGrid holding the electron pressure gradient E field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 */


/*! \brief Low-level electric field propagation function.
 *
 * Computes the upwinded electric field Y component along the cell's corresponding edge as the cross product of B and V in the XZ plane. Also includes the calculation of the maximally allowed time step.
 *
 * Expects that the correct RHO and B fields are being passed, depending on the stage of the Runge-Kutta time stepping method.
 *
 * Note that the background B field is excluded from the diffusive term calculations because they are equivalent to a current term and the background field is curl-free.
 *
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 */


/*! \brief Low-level electric field propagation function.
 *
 * Computes the upwinded electric field Z component along the cell's corresponding edge as the cross product of B and V in the XY plane. Also includes the calculation of the maximally allowed time step.
 *
 * Expects that the correct RHO and B fields are being passed, depending on the stage of the Runge-Kutta time stepping method.
 *
 * Note that the background B field is excluded from the diffusive term calculations because they are equivalent to a current term and the background field is curl-free.
 *
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 */


/*! \brief Electric field propagation function.
 *
 * Calls the general or the system boundary electric field propagation functions.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EGrid fsGrid holding the electric field
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param EGradPeGrid fsGrid holding the electron pressure gradient E field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param sysBoundaries System boundary conditions existing
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 *
 * \sa calculateUpwindedElectricFieldSimple calculateEdgeElectricFieldX calculateEdgeElectricFieldY calculateEdgeElectricFieldZ
 *
 */


/*! \brief High-level electric field computation function.
 *
 * Transfers the derivatives, calculates the edge electric fields and transfers the new electric fields.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities at runge-kutta t=0
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta t=0.5
 * \param EGrid fsGrid holding the Electric field quantities at runge-kutta t=0
 * \param EDt2Grid fsGrid holding the Electric field quantities at runge-kutta t=0.5
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param EGradPeGrid fsGrid holding the electron pressure gradient E field
 * \param momentsGrid fsGrid holding the moment quantities at runge-kutta t=0
 * \param momentsDt2Grid fsGrid holding the moment quantities at runge-kutta t=0.5
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 *
 * \sa calculateElectricField calculateEdgeElectricFieldX calculateEdgeElectricFieldY calculateEdgeElectricFieldZ
 */


/*! \brief Low-level magnetic field propagation function.
 *
 * Propagates the cell's face-averaged magnetic field components by
 * using Faraday's law on the face edges. Depending on the time order
 * of accuracy it is done in one stage or in two stages using the
 * intermediate E1 components for the first stage of the second-order
 * Runge-Kutta method and E for the other cases.
 *
 *
 * \param perBGrid fsGrid holding the perturbed B quantities at runge-kutta t=0
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta t=0.5
 * \param EGrid fsGrid holding the Electric field quantities at runge-kutta t=0
 * \param EDt2Grid fsGrid holding the Electric field quantities at runge-kutta t=0.5
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param dt Length of the time step
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 * \param doX If true, compute the x component (default true).
 * \param doY If true, compute the y component (default true).
 * \param doZ If true, compute the z component (default true).
 */


/*! \brief Low-level magnetic field propagation function.
 *
 * Propagates the magnetic field according to the system boundary conditions.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities at runge-kutta t=0
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta t=0.5
 * \param bgbGrid fsGrid holding the background field B quantities
 * \param EGrid fsGrid holding the Electric field quantities at runge-kutta t=0
 * \param EDt2Grid fsGrid holding the Electric field quantities at runge-kutta t=0.5
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param sysBoundaries System boundary conditions existing
 * \param dt Length of the time step
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 *
 * \sa propagateMagneticFieldSimple propagateMagneticField
 */


/*! \brief High-level magnetic field propagation function.
 *
 * Propagates the magnetic field and applies the field boundary conditions defined in project.h where needed.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities at runge-kutta t=0
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta t=0.5
 * \param EGrid fsGrid holding the Electric field quantities at runge-kutta t=0
 * \param EDt2Grid fsGrid holding the Electric field quantities at runge-kutta t=0.5
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 * \param dt Length of the time step
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 *
 * \sa propagateMagneticField propagateSysBoundaryMagneticField
 */


/*! \brief Low-level spatial derivatives calculation.
 *
 * For the cell with ID cellID calculate the spatial derivatives or apply the derivative boundary conditions defined in project.h.
 * Uses RHO, V[XYZ] and B[XYZ] in the first-order time accuracy method and in the second step of the second-order method,
 * and RHO_DT2, V[XYZ]1 and B[XYZ]1 in the first step of the second-order method.
 *
 * For sysBoundaryLayer 1 or 2, we are near a boundary, and we wish to use regular centered differences instead of slope limiter-adjusted values.
 * This is to minimize oscillations as a smooth behaviour is required near artificial boundaries,
 * unlike at boundaries and shocks inside the simulation domain.
 *
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 *
 * \sa calculateDerivativesSimple calculateBVOLDerivativesSimple calculateBVOLDerivatives
 */


/*! \brief High-level derivative calculation wrapper function.
 *

 * B has to be updated because after the system boundary update in propagateMagneticFieldSimple there is no consistent state of B yet everywhere.
 *
 * Then the derivatives are calculated.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta t=0.5
 * \param momentsGrid fsGrid holding the moment quantities
 * \param momentsDt2Grid fsGrid holding the moment quantities at runge-kutta t=0.5
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 * \param communicateMoments If true, the derivatives of moments (rho, V, P) are communicated to neighbours.

 * \sa calculateDerivatives calculateBVOLDerivativesSimple calculateBVOLDerivatives
 */


/*! \brief Low-level spatial derivatives calculation.
 *
 * Calculate the spatial derivatives of BVOL or set them to zero.
 *
 * For sysBoundaryLayer 1 or 2, we are near a boundary, and we wish to use regular centered differences instead of slope limiter-adjusted values.
 * This is to minimize oscillations as a smooth behaviour is required near artificial boundaries,
 * unlike at boundaries and shocks inside the simulation domain.
 *
 * \param volGrid fsGrid holding the volume averaged fields
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param sysBoundaries System boundary conditions existing
 *
 * \sa calculateDerivatives calculateBVOLDerivativesSimple calculateDerivativesSimple
 */


/*! \brief High-level derivative calculation wrapper function.
 *
 * BVOL has been calculated locally by calculateVolumeAveragedFields but not communicated.
 * For the acceleration step one needs the cross-derivatives of BVOL
 *
 * \param volGrid fsGrid holding the volume averaged fields
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 *
 * \sa calculateDerivatives calculateBVOLDerivatives calculateDerivativesSimple
 */


/*! \brief Low-level curvature calculation.
 *
 *
 * \param volGrid fsGrid holding the volume averaged fields
 * \param bgbGrid fsGrid holding the background fields
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param sysBoundaries System boundary conditions existing
 *
 * http://fusionwiki.ciemat.es/wiki/Magnetic_curvature
 *
 * \sa calculateDerivatives calculateBVOLDerivativesSimple calculateDerivativesSimple
 */


/*! \brief High-level curvature calculation wrapper function.
 *
 * \param volGrid fsGrid holding the volume averaged fields
 * \param bgbGrid fsGrid holding the background fields
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary conditions existing
 *
 * \sa calculateDerivatives calculateBVOLDerivatives calculateDerivativesSimple
 */


/*! \brief Calculates energy density for spatial cell
 *
 */


/*! \brief Low-level scaled gradients calculation
 *
 * For the SpatialCell* cell and its neighbors, calculate scaled gradients and their maximum alpha
 * The gradients are the same as in the GUMICS simulation, see
 * Janhunen, P., Palmroth, M., Laitinen, T., Honkonen, I., Juusola, L., Facsko, G., & Pulkkinen, T. I. (2012). The GUMICS-4 global MHD magnetosphere-ionosphere coupling simulation. Journal of Atmospheric and Solar - Terrestrial Physics, 80, 48-59. https://doi.org/10.1016/j.jastp.2012.03.006
 *
 */


/*! \brief High-level scaled gradient calculation wrapper function.
 *
 * Calculates gradients needed for alpha everywhere in the grid
 *
 */


/*! \brief Low-level function computing the Hall term numerator x components.
 *
 * Calls the lower-level inline templates and scales the components properly.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param perturbedCoefficients Reconstruction coefficients
 * \param i,j,k fsGrid cell coordinates for the current cell
 *
 * \sa calculateHallTerm JXBX_000_100 JXBX_001_101 JXBX_010_110 JXBX_011_111
 *
 */


/*! \brief Low-level function computing the Hall term numerator y components.
 *
 * Calls the lower-level inline templates and scales the components properly.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param perturbedCoefficients Reconstruction coefficients
 * \param i,j,k fsGrid cell coordinates for the current cell
 *
 * \sa calculateHallTerm JXBY_000_010 JXBY_001_011 JXBY_100_110 JXBY_101_111
 *
 */


/*! \brief Low-level function computing the Hall term numerator z components.
 *
 * Calls the lower-level inline templates and scales the components properly.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param perturbedCoefficients Reconstruction coefficients
 * \param i,j,k fsGrid cell coordinates for the current cell
 *
 * \sa calculateHallTerm JXBZ_000_001 JXBZ_010_011 JXBZ_100_101 JXBZ_110_111
 *
 */


/** \brief Calculate the numerator of the Hall term on all given cells.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary condition functions.
 * \param i,j,k fsGrid cell coordinates for the current cell
 *
 * \sa calculateHallTermSimple calculateEdgeHallTermXComponents calculateEdgeHallTermYComponents calculateEdgeHallTermZComponents
 */


/*! \brief High-level function computing the Hall term.
 *
 * Performs the communication before and after the computation as well as the computation of all Hall term numerator components.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param perBDt2Grid fsGrid holding the perturbed B quantities at runge-kutta half step
 * \param EHallGrid fsGrid holding the Hall contributions to the electric field
 * \param momentsGrid fsGrid holding the moment quantities
 * \param momentsDt2Grid fsGrid holding the moment quantities at runge-kutta half step
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param dMomentsGrid fsGrid holding the derviatives of moments
 * \param BgBGrid fsGrid holding the background B quantities
 * \param technicalGrid fsGrid holding technical information (such as boundary types)
 * \param sysBoundaries System boundary condition functions.
 * \param RKCase Element in the enum defining the Runge-Kutta method steps
 * \param communicateMomentsDerivatives whether to communicate derivatves with the neighbour CPUs
 *
 * \sa calculateHallTerm
 */


/*! \brief Helper function
 *
 * Divides the first value by the second or returns zero if the denominator is zero.
 *
 * \param numerator Numerator
 * \param denominator Denominator
 */


/*! \brief Low-level helper function.
 *
 * Computes the reconstruction coefficients used for field component reconstruction.
 * Only implemented for 2nd and 3rd order.
 *
 * \param perBGrid fsGrid holding the perturbed B quantities
 * \param dPerBGrid fsGrid holding the derivatives of perturbed B
 * \param perturbedResult Array in which to store the coefficients.
 * \param i,j,k fsGrid cell coordinates for the current cell
 * \param reconstructionOrder Reconstruction order of the fields after Balsara 2009, 2 used for BVOL, 3 used for 2nd-order Hall term calculations.
 */


/*! Interpolate perturbed B to arbitrary x,y,z in cell
 *  Uses the reconstruction coefficients and equations from
 *  Divergence-free reconstruction of magnetic fields and WENO schemes for magnetohydrodynamics
 *  D.S. Balsara, J. Comp. Phys., 228, 2009
 *  doi:10.1016/j.jcp.2009.03.038
 *
 * \param perBGrid perturbed B fsGrid
 * \param dPerBGrid perturbed B derivatives fsGrid
 * \param technicalGrid technical fsGrid
 * \param i local fsGrid x-index
 * \param j local fsGrid y-index
 * \param k local fsGrid z-index
 * \param x 3D global simulation x,y,z coordinates of point to interpolate to
 */


/*! Interpolate curl(perturbed B) to arbitrary x,y,z in cell
 *  Uses the reconstruction coefficients and equations from
 *  Divergence-free reconstruction of magnetic fields and WENO schemes for magnetohydrodynamics
 *  D.S. Balsara, J. Comp. Phys., 228, 2009
 *  doi:10.1016/j.jcp.2009.03.038
 *  and the wxMaxima file at
 *  doc/fieldsolver/Balsara_curlB_at_arbitrary_xyz.wxmx
 *
 * \param perBGrid perturbed B fsGrid
 * \param dPerBGrid perturbed B derivatives fsGrid
 * \param technicalGrid technical fsGrid
 * \param i local fsGrid x-index
 * \param j local fsGrid y-index
 * \param k local fsGrid z-index
 * \param x 3D global simulation x,y,z coordinates of point to interpolate to
 */


/* Particle propagation given E- and B-Field at the particle location
 * with the Boris-Method */


/* Read the cellIDs into an array */


/* For debugging purposes - dump a field into a png file
 * We're hardcodedly writing the z=0 plane here. */


/*void removedupes(std::vector<Point2f> & vec1, std::vector<Point2f> & vec2)
{
    std::unordered_set<Point2f> pointset;

    auto itor1 = vec1.begin(); auto itor2 = vec2.begin();
    while (itor1 != vec1.end())
    {
        if (pointset.find(*itor1) != pointset.end())
        {
            itor1 = vec1.erase(itor1); itor2 = vec2.erase(itor2);
        }
        else
        {
            pointset.insert(*itor1);
            itor1++; itor2++;
        }
    }
}*/


//
// NodeSetNodeList class methods
//


//
// Return a list of node ids which are present in nodelist_config but not in nodeIds.
//


// No input, use vertices_raw member variable as input.


/*
     * Population saved with interface version     Loading with interface versionIs    loaded
     * 1.1.1                                       1.1.1                               Yes
     * 1.1.1                                       1.2.1                               Yes
     * 1.1.1                                       2.1.1                               No (Exception)
     * 1.2.1                                       1.1.1                               No (Exception)
     * 2.1.1                                       1.1.1                               Yes
     *
     * Increased major version means compatibility with newer interface versions is broken.
     * Increased minor version means compatibility with older interface versions is broken.
     */


// header version 4


//JsonConfigurable::EnforceParameterAscending is not public


// Use this to control what tests are run during development


// Most of the tests will use this method and then just check who received the event/intervention


// decode shape -> std::vector<size_t>


// module name to log line map


// Either we have a log_level for this module in the map (intialized at init time), or we use the system log level.
// Either way, if the requested level is >= the setting (in terms of criticality), log it.


// -----------------------------------------------------------------
// --- Originally, this function (and for reading)return a
// --- copy of ofstream, but gcc has "deleted the assignment
// --- operator.  Hence, we need to pass it as a reference argument.
// -----------------------------------------------------------------


// See BasePropertiesTempaltes.h for template classes/methods


// If checking for new processor features is added, then please update the following
// message so that the intformation can be provided in the version information.


/////////////////////////////////////////////////////////////////////////////////////////
// config/json loading wrappers


// precision of random number obtained from a cumulative probability function


// Finds an uniformally distributed number between 0 (inclusive) and N (exclusive)


// randomRound() - rounds the 'val' to the nearest integer but randomly rounds it up or down.
// If the input value is 5.3, then 70% of the time it should return 5 and 30% of the time 6.


/******************************Public*Routine******************************\
* eGauss()                                                                 *
*                                                                          *
* Returns a normal deviate for each call.  It generates two deviates at a  *
* time and caches one for the next call.                                   *
*                                                                          *
*  Sat 26-Mar-1994 14:10:12 -by- Charles Whitmer [chuckwh]                 *
* I actually wrote this back in 1982 for some physics stuff!               *
\**************************************************************************/


// !!!!!!!!!!!!!!!
// !!! FROM NUMPY
// !!!!!!!!!!!!!!!
// Gamma-distributed random number


// Poisson() added by Philip Eckhoff, uses Gaussian approximation for ratetime>10


// Poisson_true added by Philip Eckhoff, actual Poisson, without approximation


//  expdist() added by Philip Eckhoff


// Weibull(lambda, kappa) added by Daniel Klein


// NOTE: The only reason for the arguments to be floats is that
//       it kept the regression tests from changing.
//       We get a slightly different result for 1 / inv_kappa
//       if the numbers are doubles instead of floats.  This slightly
//       different number causes thing to change slightly.


// LogLogistic(alpha, beta) added by Anna Bershteyn
// alpha is a scale parameter > 0, beta is a shape parameter > 0


//---------------------------------------------------------------------------------
// From the distributions.c:
//
// Copyright 2005 Robert Kern( robert.kern@gmail.com )
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files( the "Software" ),
// to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and / or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions :
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// NOTE: This was the notice when the binomial_approx() code was extracted.
//---------------------------------------------------------------------------------


// See numpy copyright notice above


// !!!!!!!!!!!
// !!! NUMPY
// !!!!!!!!!!!
// assuming our samples are usually small (< 10) so we need less code from numpy


// !!!!!!!!!!!
// !!! NUMPY
// !!!!!!!!!!!
// this is from random_multivariate_hypergeometric_marginals() in numpy


// This is for UTF-8 only (not for wchar or UNICODE)


// ------------------------------------------------------------------------
// --- IPKeyValueContainerFull
// ------------------------------------------------------------------------
// See BasePropertiesTempaltes.h for template classes/methods


// this used to return what(), but now it returns our customized string.
// what() can always be called directly in case our carefully formed message
// from parameters lost something really useful! Callers should not assume
// _msg includes what().


// This is to be used in the default section of most switch statements.


// This is to be used when a map is searched for a key that is believed
// to exist but is not found.


// two functions. second is wrapper around this. Can consolidate into single.


// We have sets/vectors from json arrays, now add maps from json dictonaries
// This will be for specific piece-wise constant maps of dates (fractional years)
// to config values (floats first).


// ------------------------------------------------------
// --- Methods for creating an object from a string and
// --- for creating the string from the object
// ------------------------------------------------------


// ----------------------------------------------
// --- Methods for getting values from an object
// ----------------------------------------------


// -------------------------------------------
// --- Methods for getting values from values
// -------------------------------------------


// ---------------------------------------------------------
// --- Methods for Adding and Removing items from an Object
// ---------------------------------------------------------


// -------------------------------------
// --- Methods for manipulating an Array
// -------------------------------------


// ----------------------------------------------------
// --- Methods for getting an Iterator from an Object
// ----------------------------------------------------


// Derived constructor calls base constructor to initialized reduced timesteps etc.


// ------------------------------------------------------------------------
// --- NOTE: I want to use templates for the string and double versions but
// --- I'm not sure how to handle the IJsonObjectAdapter method call.
// --- I tried type_traits but I still wasn't getting a good code savings.
// ------------------------------------------------------------------------


// Converting +ve microscopic fields of view out of 200 slide views to parasite densities


// Adding uncertainty to PCR derived densities a la Walker et al. (2015)


// Smears infectiousness values using a binomial draw given 40 draws


// Just calling the base class but for demo purposes leaving in because I can imagine wanting to do this custom.


// not sure whether to leave this in custom demo subclass


// Copy "len" bytes from "src" to "op", one byte at a time.  Used for
// handling COPY operations where the input and output regions may
// overlap.  For example, suppose:
//    src    == "ab"
//    op     == src + 2
//    len    == 20
// After IncrementalCopy(src, op, len), the result will have
// eleven copies of "ab"
//    ababababababababababab
// Note that this does not match the semantics of either memcpy()
// or memmove().


// Read the uncompressed length stored at the start of the compressed data.
// On succcess, stores the length in *result and returns true.
// On failure, returns false.


// The durations are used in sequence as a series of relative deltas from the Start_Day
// of the campaign event.
// t(now).......+t0....+t1...............+t2.+t3....+t4


// Each time this is called, the HSB intervention is going to decide for itself if
// health should be sought. For start, just do it based on roll of the dice. If yes,
// an intervention needs to be created (from 'actual' config) and distributed to the
// individual who owns us.


// This is deliberately broken out into separate function so that derived classes can invoke
// without calling SD::Configure -- if they want Positive_Dx_Config/Event but not Treatment_Fraction.


// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! NOTE: The naming of onPatientDefault() and onNegativeTestResult() implies that
// !!! "on" the <event> occurring this action will occur.  "on" the event of patient
// !!! default the onPatientDefault() action is performed.  If things were consistent,
// !!! positiveTestDistribute() would be called onPositveTestResult().
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


//returns false if didn't get the intervention


// runs on a positive test when in positive treatment fraction


// runs on a negative test when in negative treatment fraction


// Each time this is called, the HSB intervention is going to decide for itself if
// health should be sought. For start, just do it based on roll of the dice. If yes,
// an intervention needs to be created (from what config?) and distributed to the
// individual who owns us. Hmm...


// This is a debug only utility function to dump out actual dosing calendars.


// todo: lift to HIVIntervention or helper function (repeated in HIVDelayedIntervention)


// static: doesn't use any member variables, just lives in this class for convenience.
// Purpose: This function converts a WHO HIV stage (1-4 really, but 1.0-4.99 for us)
// into a human body weight in kg. It does a linear interpolation on the hardcoded array.


// This is an implementation of the Cox Proportional Model (e.g., http://en.wikipedia.org/wiki/Cox_proportional_hazards_model)
// The values are taken from the IeDEA website (http://www.iedea-sa.org/index.php?id=2856)


// context is nothing more than ISupports really, and it's a pointer to the individual's
// intervention container, not the individual itself. It was gotten by a call to
// pIndividual->GetInterventionsContext().


// needed for VaccineTake


// I think we can get rid of this altogether


/* customized variant of memcpy, which can overwrite up to 7 bytes beyond dstEnd */


/* hidden debug function */
/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */


/* Hidden debug function, to force external dictionary mode */


/*
 * If you prefer dynamic allocation methods,
 * LZ4_createStreamDecode()
 * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
 */


/*!
 * LZ4_setStreamDecode() :
 * Use this function to instruct where to find the dictionary.
 * This function is not necessary if previous data is still available where it was decoded.
 * Loading a size of 0 is allowed (same effect as no dictionary).
 * Return : 1 if OK, 0 if error
 */


/*
*_continue() :
    These decoding functions allow decompression of multiple blocks in "streaming" mode.
    Previously decoded blocks must still be available at the memory position where they were decoded.
    If it's not possible, save the relevant part of decoded data into a safe buffer,
    and indicate where it stands using LZ4_setStreamDecode()
*/


// small utility function that helps PFA not put a couple into a duplicate relationship


// I can't seem to make this const due to the use of individual_visit_function


// Update() is called for all the coordinators before calling UpdateNodes()


//! \param start if set to true will initialize and then start the
//! timer.


//! You can get the result of the stopwatch start-stop sequence at
//! your leisure.


// The purpose of this function is to reduce the individual's CD4 count all at once
// as dictated by the value of dt passed in. This does not represent a real-world
// behaviour. Rather it is for Outbreaks where we are pretending time has elapsed.


// The Update function primarily increases or decreases the value of CD4count depending
// on whether or not the individual has untreated HIV -- decreases -- or is on a viral
// suppression intervention (e.g., ART) -- increases.


// source is a block of LZ4 compressed data with the size of the uncompressed data prepended


// This Configure() is intended to be used by NodeVector to get the LarvalHabitatMultiplier
// out of the demographics file.


//NOTE: we use a std::list here so that we can keep
//the list sorted as we add crossovers.


// index of the genome


// ----------------------------------------------------------------------------------
// --- The idea with this algorithm is to draw one random number, look up in a table
// --- how to arrange the chromosomes into the different genomes, and do this with
// --- a minimal amount of copying and random numbers.
// ----------------------------------------------------------------------------------


// ------------------------------------------------------------
// --- This is really just your basic swap between two objects.
// ------------------------------------------------------------


// ------------------------------------------------------------------------
// --- This is a 3-way swap.  The algorithm is circular:
// ---    tmp<-1
// ---    1 <- 2
// ---    2 <- 3
// ---    3 <- tmp
// ------------------------------------------------------------------------


// ------------------------------------------------------------------------
// --- This is a 4-way swap.  The key to this algorithm is the use of the
// --- index values.  It is "circular" in that you first copy the data in the
// --- first index into tmp, then copy the data from the genome indicated by
// --- the index.  The genome we copied 'from' becomes the one we want to copy 'to'.
// --- Continue this until all four indexes are used.
// ------------------------------------------------------------------------


// ---------------------------------------------------------------------------------------------
// --- GH-4251 - Number of Infectious Bites in Vector Model and Individual Are Not Similar
// --- Dividing the amount deposited by the population average of the the probablity of
// --- the vector transmitting.  All the values deposited will be normalized by the total
// --- total number of people in the population - StrainAwareTransmissionGroups::EndUpdate().
// --- IndividualHumanVector::Expose() will take the total contagion from SATG and multiply
// --- this by the individuals probability of the vector transmitting to them.  This resulting
// --- value will be used in the Poisson draw to determine how many bites the person received.
// ---------------------------------------------------------------------------------------------


// Return a vector that contains a randomly order set of indexes that are from 0 to (N-1)


// Genomes are considered similar if for each locus (ignoring gender), the set of allele are
// the same for each genome.  For example:
//    1-1 & 1-1 = similar     - both genomes have 1
//    1-0 & 0-1 = similar     - both genomes have 0 and 1
//    2-0 & 0-1 = NOT similar - the right genome does not have 2 and the left does not have 1
//    1-1 & 0-1 = NOT similar - the left genome does not have 0


// This was done with macros, but prefer actual code.


// method 1 for VisitIndividuals uses a functor/lambda function


// method 2 for VisitIndividuals uses an interface


// First cut of this function writes the intervention report to stdout. It is an abbreviated,
// 1-line-per-intervention report.


// needed for testing


// Don't need this
//GeneticProbability GeneticProbability::operator/( const GeneticProbability& rhs ) const;


// See header file for more info.


// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! In a scenario like 25_Madagascar that has 30000+ nodes,
// !!! we really have to minimize the data that is being shared
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


// ------------------------------------------------------------------------------------------------------
// --- WARNING: This does not use the IVisitIndividual interface method of distributing the intervention
// --- like StandardInterventionDistributionEventCoordinator.
// ------------------------------------------------------------------------------------------------------


//static std::vector<PartnerScore> partner_score_list;


// Obviously don't need this if it's not doing anything useful.


// The purpose of this function is to calculate the existing coverage of the attribute in question
// and then to set the target coverage based on the error between measured and configured (for current time).


// called by demographic file Populate()


// Basic simulation main loop with reporting


// --------------------------------------------------------------------------------------
// --- NOTE: Once upon a time, we had the cohorts keeping track of eggs but we switched
// --- to number of vectors because when a vector dies we lose the entire batch of eggs,
// --- not just a portion of it.
// --------------------------------------------------------------------------------------


// AddNode
// EventCoordinators track nodes. Nodes can be used to get individuals, who can be queried for an intervention


// these do nothing for now


// This code now supports loading linux shared objects for reproters once again in the same way as on windows.
// Note that this is not yet true of interventions or sim types -- though that was true in the original version.
// There has been little attempt to optimize this for code reuse between os-es. And that may not be desirable
// from a readability point of view. If one were to make any change, it might be to optimize around error handling.
// The biggest complaint about non-monolithic code is confusion about when it doesn't work. That can be ameliorated
// in large part but top-notch error handling.


// The purpose of this function is to calculate the existing coverage of the intervention in question
// and then to set the target coverage based on the error between measured and configured (for current time).


// The reason for this explicit QI (instead of macro) is to let us resolve
// the IJsonSerializable cast which is ambiguous and must be done via
// a specific intermediate.


// This method finds the lowest 0 in the relationshipSlots bitmask


// takes in age in days and returns age in days


// Sums up the current parasite counts for the infection and determines if the infection is cleared or if death occurs this time step
// All end of time step bookkeeping, basically


// Calculates the IRBC killing from drugs and immune action


// Calculates stimulation of immune system by malaria infection


// Calculates immature gametocyte killing from drugs and immune action


// Calculates the antigenic switching when an asexual cycle completes and creates next generation of IRBC's


// Moves all falciparum gametocytes forward a development stage when an asexual cycle completes, and creates the stage 0 immature gametocytes


// Process all infected hepatocytes


// campaign semaphore interface (IIndividualHumanHIV)


// TODO: port normal exposure_to_infectivity logic to this pattern as well <ERAD-328>


/* clorton
    std::string IndividualHuman::toJson()
    {
        IJsonObjectAdapter* adapter = CreateJsonObjAdapter();
        adapter->CreateNewWriter();
        adapter->BeginObject();

        adapter->Insert("suid", suid.data);
        adapter->Insert("age", m_age);
        adapter->Insert("gender", m_gender);
        adapter->Insert("mc_weight", m_mc_weight);
        adapter->Insert("daily_mortality_rate", m_daily_mortality_rate);
        adapter->Insert("above_poverty");
        adapter->Insert("is_pregnant", is_pregnant);
        adapter->Insert("pregnancy_timer", pregnancy_timer);

        // susceptibility
        // infections
        // interventions
        // transmissionGroupMembership
        // transmissionGroupMembershipByRoute

        adapter->Insert("is_infected", m_is_infected);
        adapter->Insert("infectiousness", infectiousness);
        adapter->Insert("Inf_Sample_Rate", Inf_Sample_Rate);
        adapter->Insert("cumulativeInfs", cumulativeInfs);

        adapter->Insert("new_infection_state", int(m_new_infection_state));
        adapter->Insert("StateChange", int(StateChange));

        adapter->Insert("migration_mod", migration_mod);
        adapter->Insert("migration_type", migration_type);
        adapter->Insert("migration_destination", migration_destination.data);
        adapter->Insert("time_to_next_migration", time_to_next_migration);
        adapter->Insert("will_return", will_return);
        adapter->Insert("outbound", outbound);
        adapter->Insert("max_waypoints", max_waypoints);
        // waypoints
        // waypoints_trip_type

        // Properties

        // parent

        adapter->EndObject();

        std::string s(adapter->ToString());
        return s;
    }

    void IndividualHuman::fromJson(std::string& json)
    {
        IJsonObjectAdapter* adapter = CreateJsonObjAdapter();
        adapter->Parse(json.c_str());

        suid.data = adapter->GetUint("suid");
        m_age = adapter->GetFloat("age");
        m_gender = adapter->GetInt("gender");
        m_mc_weight = adapter->GetFloat("mc_weight");
        m_daily_mortality_rate = adapter->GetFloat("daily_mortality_rate");
        is_pregnant = adapter->GetBool("is_pregnant");
        pregnancy_timer = adapter->GetBool("pregnancy_timer");

        // susceptibility
        // infections
        // interventions
        // transmissionGroupMembership
        // transmissionGroupMembershipByRoute

        m_is_infected = adapter->GetBool("is_infected");
        infectiousness = adapter->GetFloat("infectiousness");
        Inf_Sample_Rate = adapter->GetFloat("Inf_Sample_Rate");
        cumulativeInfs = adapter->GetInt("cumulativeInfs");

        m_new_infection_state = NewInfectionState::_enum(adapter->GetInt("new_infection_state"));
        StateChange = HumanStateChange(adapter->GetInt("StateChange"));

        migration_mod = adapter->GetFloat("migration_mod");
        migration_type = adapter->GetInt("migration_type");
        migration_destination.data = adapter->GetUint("migration_destination");
        time_to_next_migration = adapter->GetFloat("time_to_next_migration");
        will_return = adapter->GetBool("will_return");
        outbound = adapter->GetBool("outbound");
        max_waypoints = adapter->GetInt("max_waypoints");
        // waypoints
        // waypoints_trip_type

        // Properties

        // parent

        delete adapter;
    }
*/


///////////////////////////////////////////////////////////////////////////
// SPECIFIC TYPES OF RELATIONSHIPS HERE //
///////////////////////////////////////////////////////////////////////////


// Let's use the MSP version of antibody growth in the base class ...


// Different arguments used by CSP update called directly from IndividualHumanMalaria::ExposeToInfectivity
// and also in SusceptibilityMalaria::updateImmunityCSP


// normalize by timestep and create derived channels


// Check simulation abort conditions


// Use with __try {} __except(filter(GetExceptionCode(), GetExceptionInformation())) { MPI_Abort(EnvPtr->world, -1); }
//
//    static char* section;
//
//    static int filter(unsigned int code, struct _EXCEPTION_POINTERS* ep)
//    {
//        cout << '[' << EnvPtr->MPI.Rank << "] " << "Section: " << section << endl; cout.flush();
//        cout << '[' << EnvPtr->MPI.Rank << "] " << "Exception code      = " << code << endl; cout.flush();
//        cout << '[' << EnvPtr->MPI.Rank << "] " << "EP.ExceptionCode    = " << ep->ExceptionRecord->ExceptionCode << endl; cout.flush();
//        cout << '[' << EnvPtr->MPI.Rank << "] " << "EP.ExceptionAddress = " << ep->ExceptionRecord->ExceptionAddress << endl; cout.flush();
//
//        void* callers[32];
//        auto frames = CaptureStackBackTrace( 0, 32, callers, nullptr);
//        for (size_t i = 0; i < frames; i++) {
//            cout << '[' << i << "] " << callers[i] << endl;
//        }
//        cout.flush();
//
//        return EXCEPTION_EXECUTE_HANDLER;
//    }


//------------------------------------------------------------------
//   First timestep Populate() methods
//------------------------------------------------------------------


//------------------------------------------------------------------
//   Individual migration methods
//------------------------------------------------------------------


// public constructor implementations


//protected constructor implementations


// ------------------------------------------------------------------------------
// In DanB's understanding, the idea of "germline gene drives" is built on
// the idea that allele in the entities DNA will have blueprints for producing
// Cas9 and guide RNA (gRNA).  During Interphase (which happens right before
// meiosis) when the chromosomes are still paired up (one from each parent),
// the Cas9 and gRNA are produced.  These guys will temporarily team up and
// look for the targeted DNA strand, usually a wild-type allele.  When found,
// the Cas9 will cut out the targeted allele and then let
// Homology Directed Repair (HDR) do the work of copying the desired allele
// from the sister stand/chromosome into the "hole" created by the Cas9.
// If the Cas9+gRNA cannot find the targeted allele, they break up and the
// Cas9 can look for another gRNA.  [Shirley -It's true-ish in that the Cas9+gRNA
// could break up at any time (though they have a really high affinity for each
// other, so not too often) such that the free Cas9 can then run into and bind
// another gRNA, but it's not really on purpose if the targeted allele can't
// be found. It just happens randomly.]
//
// There can be problems during this process.  The Cas9+gRNA might not find
// the targeted allele.  There could be problems during cutting that cause a
// mutation to occur.  There can be problems with the copying.  One type of
// mutation can come from Non-Homologous End Joining (NHEJ) that happens when
// you have double stranded breaks.  I don't know how we get those exactly,
// but the main idea is that you get mutations and sometimes these mutations
// can make the cell non-viable while others can develop a "resistance" to
// the drive.  This resistance is the formation of a valid allele that the
// drive's gRNA doesn't recognize.  This means no cutting occurs which means
// no copying occurs and no propagation of the  desired allele.
//
// In the Classic gene drive case, the DNA has the Cas9, gRNA, and the desired
// allele (with some special phenotypic property) combined together.
// During Interphase, if the Cas9+gRNA finds the targeted allele, it will cut
// it out and copy over the blueprints for the Cas9, gRNA, and desired allele.
//
// In contrast, the integral gene drive is based on the idea of having a driver
// that has the Cas9+gRNA that knows how to find its self plus an effector, our
// desired allele, that has its own gRNA. The effector allele doesn't need to be
// bundled with the driving allele.  The Cas9 produced by the driver can also
// team up with the gRNA produced by the effector so it can cut out the targeted
// allele where we want the effector to go.
//
// In the case where you have more than one driver, a Cas9 and gRNA are being
// produced for each driver.  If you have an effector, it is also producing gRNA.
// We assume that a single driver produces an "equal" number of Cas9 and gRNA.
// The presence of more drivers should not impact the likelihood of cutting the
// targeted allele because they are all pairing up evenly.  However, the extra
// Cas9 from the multiple drivers can impact the likelihood of cutting the
// effector that is producing gRNA but not Cas9.  In the single driver case,
// there is one set of Cas9 and two sets of gRNA.  In the two driver case,
// there are two sets of Cas9 and three sets of gRNA, hence, there is a greater
// likelihood of a Cas9 pairing up with the gRNA from the effector.
// ------------------------------------------------------------------------------


// returns false if something broke


//
// INodeVectorInterventionEffects; (The Getters)
//


// override this because we need to skip every nrmSize entries when doing the sum...


// purposelly making rSelectedIndicies non-const so that we can remove values
// once we find a vector for the indicie


// normalize by time step and create derived channels


// This is just to avoid Disease Deaths not broken down by props which is in base class. Why is it there?


// <ERAD-291>
// TODO: Make simulation object initialization more consistent.  Either all pass contexts to constructors or just have empty constructors


//------------------------------------------------------------------
//   Every timestep Update() methods
//------------------------------------------------------------------


// This allows subclass to override this function and replace it, specifically PyMod in which node has no individuals and
// individual parameters are passed


// This function allows one to scale the initial population by a factor without modifying an input demographics file.


// This function adds the initial population to the node according to behavior determined by the settings of various flags:
// (1) ind_sampling_type: TRACK_ALL, FIXED_SAMPLING, ADAPTED_SAMPLING_BY_POPULATION_SIZE, ADAPTED_SAMPLING_BY_AGE_GROUP, ADAPTED_SAMPLING_BY_AGE_GROUP_AND_POP_SIZE
// (2) demographics_initial
// (3) enable_age_initialization, age_initialization_distribution_type
// (4) vital_birth_dependence: INDIVIDUAL_PREGNANCIES must have initial pregnancies initialized


// This function adds newborns to the node according to behavior determined by the settings of various flags:
// (1) ind_sampling_type: TRACK_ALL, FIXED_SAMPLING, ADAPTED_SAMPLING_BY_POPULATION_SIZE, ADAPTED_SAMPLING_BY_AGE_GROUP, ADAPTED_SAMPLING_BY_AGE_GROUP_AND_POP_SIZE
// (2) demographics_birth
// (3) enable_maternal_infection_transmission
// (4) vital_birth_dependence: FIXED_BIRTH_RATE, POPULATION_DEP_RATE, DEMOGRAPHIC_DEP_RATE. (INDIVIDUAL_PREGNANCIES handled in PopulateNewIndividualFromPregnancy)


// Populate with an Individual as an argument
// This individual is the mother, and will give birth to a child under vital_birth_dependence==INDIVIDUAL_PREGNANCIES
// This function should only get called frmy PyMod


//------------------------------------------------------------------
//   Campaign event related
//------------------------------------------------------------------


// Determines if Node is in a defined lat-long polygon
// checks for line crossings when extending a ray from the Node's location to increasing longitude
// odd crosses included, even crossed excluded


// TODO: Cache results so we don't recalculate all the time. (that's why it's non-const)


//------------------------------------------------------------------
//   Assorted getters and setters
//------------------------------------------------------------------


// Methods for implementing time dependence in infectivity, birth rate, migration, etc.


// count of distributed merge


// Find Kth element without recusion


//RandomForest::RandomForest(const char*modelPath)
//{
//	readModel(modelPath,nproc);
//}


/*
int main(int argc, char **argv) {
	char filename[4096];
	if (argc < 5) {
		fprintf(stderr, "Argument needed: <data file name> <num_trees> <selection_size> <training ratio>\n");
		return -1;
	}
	strcpy(filename, argv[1]);
	//mw_replicated_init((long *)&g_numTrees, atol(argv[2]));
	//mw_replicated_init((long *)&g_selectionSize, atol(argv[3]));

	randomForestClassifier_initialize(atol(argv[2]), AUTO, 0);

	mw_replicated_init((long *)&g_trainPercent, 100 * atof(argv[4]));

	parseFile_sklearn(filename);

	starttiming();
	volatile uint64_t starttimer = CLOCK();

	initTrees();

	//train();
	randomForestClassifier_train();

	g_rightResults = 0;
	g_wrongResults = 0;
	g_rightResults = 1;

	test();

	volatile uint64_t endtimer = CLOCK();
	uint64_t delta = endtimer - starttimer;
	LOG_INFO("Completed in %lu cycles Right %lu vs Wrong %lu (accuracy %.2f%%)\n", delta, g_rightResults, g_wrongResults, (double)g_rightResults / (double)(g_rightResults + g_wrongResults) * 100.0);

	return 0;
}

// Assuming the following format:
// First line: number of entries,number of features per line
// All others: CSV features. We assume only the useful ones have already been selected
void parseFile_sklearn(const char *filename) {
	FILE *fd = fopen(filename, "r");
	if (!fd) {
		fprintf(stderr, "Could not open data file %s\n", filename);
		exit(-1);
	}
	uint64_t nsamp, nf;
	fscanf(fd, "%lu,%lu,", &nsamp, &nf);
	uint64_t ntrain = nsamp * ((double)g_trainPercent / 100.0);
	uint64_t ntest = nsamp - ntrain;
	//mw_replicated_init((long *)&g_numTrainSamples, (long)ntrain);
	mw_replicated_init((long *)&g_numTestSamples, (long)ntest);
	//mw_replicated_init((long *)&g_numFeatures, (long)nf);
	uint64_t nc = 1;
	while (true) {
		char c;
		fread(&c, 1, sizeof(char), fd);
		if (c == ',')
			nc++;
		if (c == '\n')
			break;
	}
//	mw_replicated_init((long *)&g_numClasses, (long)nc);
	randomForestClassifier_initializeTraining(ntrain, nf, nc);

	LOG_INFO("=== Reading %s #samples: %lu %lu #features: %lu #classes: %lu Number trees= %lu Selection size= %lu ===\n", filename, g_numTrainSamples, g_numTestSamples, g_numFeatures, g_numClasses, g_numTrees, g_selectionSize);

#ifdef INVERT_TEST_DATA
	double **samplesTestTmp = (double **)mw_malloc2d(nf, ntest * sizeof(double));
#else
	double **samplesTestTmp = (double **)mw_malloc2d(ntest, nf * sizeof(double));
#endif
	mw_replicated_init((long *)&g_testSamples, (long)samplesTestTmp);

	double **samplesWeightsTmp = (double **)mw_malloc2d(g_numTrees, ntrain * sizeof(double));
	mw_replicated_init((long *)&g_samplesWeights, (long)samplesWeightsTmp);

	uint64_t *samplesLabelsTestTmp = (uint64_t *)mw_malloc1dlong(ntest);
	mw_replicated_init((long *)&g_testSamplesLabels, (long)samplesLabelsTestTmp);

	uint64_t **samplesTestClassesTmp = (uint64_t **)mw_malloc2d(ntest, g_numClasses * sizeof(uint64_t));
	mw_replicated_init((long *)&g_testSamplesClassesVotes, (long)samplesTestClassesTmp);

	for (uint64_t s = 0; s < ntest; s++)
		memset(g_testSamplesClassesVotes, 0 , g_numClasses * sizeof(uint64_t));

	double *gc_samples = (double *)malloc(ntrain * nf * sizeof(double));
	uint64_t *gc_classes = (uint64_t *)malloc(ntrain * sizeof(uint64_t));

	uint64_t foldValue = nsamp / g_numTestSamples;
	LOG_DEBUG("folded: %lu\n", foldValue);
	uint64_t ntr = 0; // training
	uint64_t ntt = 0; // test
	for (uint64_t s = 0; s < nsamp; s++) {
		bool testing = (s % foldValue == 0);
		//if (testing) {
		//	LOG_DEBUG("Testing: %lu %lu\n", s, ntt);
		//}
		for (uint64_t f = 0; f < g_numFeatures; f++) {
			double val;
			fscanf(fd, "%lf,", &val);
			if (!testing) {
				gc_samples[ntr * nf + f] = val;
	//			g_trainSamples[ntr][f] = val;
			} else
#ifdef INVERT_TEST_DATA
				g_testSamples[f][ntt] = val;
#else
				g_testSamples[ntt][f] = val;
#endif
		}
		uint64_t label;
		fscanf(fd, "%lu\n", &label);
		if (!testing) {
			gc_classes[ntr] = label;
	//		g_trainSamplesLabels[ntr] = label;
			ntr++;
		} else
			g_testSamplesLabels[ntt++] = label;
	}
	fclose(fd);

	randomForestClassifier_fillTrainingData(gc_samples, gc_classes);
	free(gc_samples);
	free(gc_classes);
}

*/


// At this point, the node inputSamples are filled, with data in order


// void computeThreshold(CandidateNode **node)


// initialization for the read model path
// set up distributed array that will point to trees


/*-----------------------------------------------------------------------------------------------------------------------------
 * UsageAndExit()
 * Display syntax and exit
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * SignalHandler()
 * Signal handler for shutdowns on ctrl-c
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * InitHandles()
 * Open necessary connections, including handle
 * to device and output to webservice or file.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * CloseHandlesAndDelete()
 * Close any open IO Handles, reclaim memory.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * InitWSConnection()
 * Open the connection to the ROS bridge server
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * CloseWSConnection()
 * Close the connection to the ROS bridge server
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * XtsCallbackFunction()
 * The scan callback.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * GetDataAndPublish()
 * Get the data from the device and publish it
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * MakeScanJSON()
 * Create the JSON for the ROS bridge publish request.
 *
 * RosBridge publish request JSON:
 *     { "op" : "publish",
 *       "topic" : <topic>,
 *       "msg" : <msg_json> }
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * MakeScanJSON()
 * Create the JSON for the ROS bridge publish request
 * for data from file (CMatrix<FLOAT>).
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * PublishFromFile()
 * Publish from a sample file - it assumes scan size is 96 columns x 20 rows. As noted in the argument
 * parsing section above, the obscure case of file to file supported in this function for development
 * testing purposes.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * PublishMessage()
 * Send the JSON message to the web service.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * WriteRecordHeader()
 * Write the frame header to the output stream.
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * WriteScanToFile()
 * Write scan data to the output stream - for data directly from the sensor pad (WORD's).
 *-----------------------------------------------------------------------------------------------------------------------------*/


/*-----------------------------------------------------------------------------------------------------------------------------
 * WriteScanToFile()
 * Write scan data to the output stream - for data from file (FLOAT's).
 *-----------------------------------------------------------------------------------------------------------------------------*/


// This example reads basic information from config file
// and prints out the expected configuration specification.


// This example reads complex types from config file using method chains.


// This example reads basic information from config file
// and reacts on missing mandatory values.


// function to print UBJSON's diagnostic format


/*!
    @param[in] format  the binary format to parse
    @param[in] sax_    a SAX event processor
    @param[in] strict  whether to expect the input to be consumed completed

    @return
    */


/*!
    @brief Read a BSON element list (as specified in the BSON-spec)

    The same binary layout is used for objects and arrays, hence it must be
    indicated with the argument @a is_array which one is expected
    (true --> array, false --> object).

    @param[in] is_array Determines if the element list being read is to be
                        treated as an object (@a is_array == false), or as an
                        array (@a is_array == true).
    @return whether a valid BSON-object/array was passed to the SAX parser
    */


/*!
    @param[in] get_char  whether a new character should be retrieved from the
                         input (true, default) or whether the last read
                         character should be considered instead

    @return whether a valid CBOR value was passed to the SAX parser
    */


/*!
    @param[in] format   the current format (for diagnostics)
    @param[in] context  further context information (for diagnostics)
    @return whether the last read character is not EOF
    */


/// return name of values of type token_type (only used for errors)


/*!
    @brief scan a string literal

    This function scans a string according to Sect. 7 of RFC 7159. While
    scanning, bytes are escaped and copied into buffer token_buffer. Then the
    function returns successfully, token_buffer is *not* null-terminated (as it
    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
    string.

    @return token_type::value_string if string could be successfully scanned,
            token_type::parse_error otherwise

    @note In case of errors, variable error_message contains a textual
          description.
    */


/*!
    @brief unget current character (read it again on next get)

    We implement unget by setting variable next_unget to true. The input is not
    changed - we just simulate ungetting by modifying chars_read_total,
    chars_read_current_line, and token_string. The next call to get() will
    behave as if the unget character is read again.
    */


/*!
    @brief remove last reference token

    @pre not `empty()`

    @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back}

    @complexity Constant.

    @throw out_of_range.405 if JSON pointer has no parent

    @since version 3.6.0
    */


/*!
    @brief determine the type prefix of container values

    @note This function does not need to be 100% accurate when it comes to
          integer limits. In case a number exceeds the limits of int64_t,
          this will be detected by a later call to function
          write_number_with_ubjson_prefix. Therefore, we return 'L' for any
          value that does not fit the previous limits.
    */


/*!
@brief appends a decimal representation of e to buf
@return a pointer to the element following the exponent.
@pre -1000 < e < 1000
*/


/*!
    @brief internal implementation of the serialization function

    This function is called by the public member function dump and organizes
    the serialization internally. The indentation level is propagated as
    additional parameter. In case of arrays and objects, the function is
    called recursively.

    - strings and object keys are escaped using `escape_string()`
    - integer numbers are converted implicitly via `operator<<`
    - floating-point numbers are converted to a string using `"%g"` format

    @param[in] val             value to serialize
    @param[in] pretty_print    whether the output shall be pretty-printed
    @param[in] indent_step     the indent level
    @param[in] current_indent  the current indent level (only used internally)
    */


/*!
    @brief dump escaped string

    Escape a string by replacing certain special characters by a sequence of an
    escape character (backslash) and another character and other control
    characters by a sequence of "\u" followed by a four-digit hex
    representation. The escaped string is written to output stream @a o.

    @param[in] s  the string to escape
    @param[in] ensure_ascii  whether to escape non-ASCII characters with
                             \uXXXX sequences

    @complexity Linear in the length of string @a s.
    */