/*******************************************************************************
* This file is part of SWIFT.
* Copyright (c) 2016 Matthieu Schaller (schaller@strw.leidenuniv.nl)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
******************************************************************************/
#ifndef SWIFT_TIMELINE_H
#define SWIFT_TIMELINE_H
/* Config parameters. */
#include
/* Local headers. */
#include "inline.h"
#include "intrinsics.h"
#include
#include
typedef long long integertime_t;
typedef int8_t timebin_t;
/*! The number of time bins */
#define num_time_bins 56
/*! The maximal number of timesteps in a simulation */
#define max_nr_timesteps (1LL << (num_time_bins + 1))
/*! Fictious time-bin to hold inhibited particles */
#define time_bin_inhibited (num_time_bins + 2)
/*! Fictious time-bin to hold particles not yet created */
#define time_bin_not_created (num_time_bins + 3)
/*! Fictitious time-bin for particles not awaken */
#define time_bin_not_awake (-num_time_bins)
/* Maximal difference in time-bins between neighbouring particles */
#define time_bin_neighbour_max_delta_bin 2
/**
* @brief Returns the integer time interval corresponding to a time bin
*
* @param bin The time bin of interest.
*/
__attribute__((const)) static INLINE integertime_t
get_integer_timestep(const timebin_t bin) {
if (bin <= 0) return 0;
return 1LL << (bin + 1);
}
/**
* @brief Returns the time bin corresponding to a given time_step size.
*
* Assumes that integertime_t maps to an unsigned long long.
* Given our definitions, this is log_2 of the time_step rounded down minus one.
*
* We use a fast (but exact for any non-zero value) logarithm in base 2
* calculation based on the bit representation of the number:
* log_2(x) = (number of bits in the type) - (number of leading 0-bits in x) - 1
*
* @param time_step An integer time-step length.
*/
__attribute__((const)) static INLINE timebin_t
get_time_bin(const integertime_t time_step) {
/* ((int) log_2(time_step)) - 1 */
return (timebin_t)((8 * sizeof(integertime_t) - 2) -
intrinsics_clzll((unsigned long long)time_step));
}
/**
* @brief Returns the physical time interval corresponding to a time bin.
*
* @param bin The time bin of interest.
* @param time_base the minimal time-step size of the simulation.
*/
__attribute__((const)) static INLINE double get_timestep(
const timebin_t bin, const double time_base) {
return get_integer_timestep(bin) * time_base;
}
/**
* @brief Returns the integer time corresponding to the start of the time-step
* given by a time-bin.
* If the current time is a possible beginning for the given time-bin, return
* the current time minus the time-step size.
*
* @param ti_current The current time on the integer time line.
* @param bin The time bin of interest.
*/
__attribute__((const)) static INLINE integertime_t
get_integer_time_begin(const integertime_t ti_current, const timebin_t bin) {
const integertime_t dti = get_integer_timestep(bin);
if (dti == 0)
return 0;
else
return dti * ((ti_current - 1) / dti);
}
/**
* @brief Returns the integer time corresponding to the end of the time-step
* given by a time-bin.
* If the current time is a possible end for the given time-bin, return the
* current time.
*
* @param ti_current The current time on the integer time line.
* @param bin The time bin of interest.
*/
__attribute__((const)) static INLINE integertime_t
get_integer_time_end(const integertime_t ti_current, const timebin_t bin) {
const integertime_t dti = get_integer_timestep(bin);
if (dti == 0)
return 0;
else {
const integertime_t mod = ti_current % dti;
if (mod == 0)
return ti_current;
else
return ti_current - mod + dti;
}
}
/**
* @brief Returns the highest active time bin at a given point on the time line.
*
* @param time The current point on the time line.
*/
__attribute__((const)) static INLINE timebin_t
get_max_active_bin(const integertime_t time) {
if (time == 0) return num_time_bins;
timebin_t bin = 1;
while (!((1LL << (bin + 1)) & time)) ++bin;
return bin;
}
/**
* @brief Returns the lowest active time bin at a given point on the time line.
*
* @param ti_current The current point on the time line.
* @param ti_old The last synchronisation point on the time line.
*/
__attribute__((const)) static INLINE timebin_t
get_min_active_bin(const integertime_t ti_current, const integertime_t ti_old) {
const timebin_t min_bin = get_max_active_bin(ti_current - ti_old);
return min_bin;
}
#endif /* SWIFT_TIMELINE_H */