Constructs a grid with the given minimum grid coordinates and grid length.
If you need periodic boundaries you have to use this constructor to set the correct length to use for wrapping particles around the borders.
121 :
length_(min_and_length.second) {
122 const auto min_position = min_and_length.first;
123 const SizeType particle_count = particles.size();
131 cells_.emplace_back(particles.copy_to_vector());
142 const int max_cells =
144 ? std::cbrt(particle_count)
145 : std::max(2,
static_cast<int>(std::cbrt(particle_count)));
150 std::array<double, 3> index_factor = {1. / max_interaction_length,
151 1. / max_interaction_length,
152 1. / max_interaction_length};
157 :
static_cast<int>(std::floor(
length_[i] * index_factor[i]));
169 std::string error_box_too_small =
170 "Input error: Your box is too small for the grid.\n"
171 "The minimal length of the box is given by: " +
172 std::to_string(2 * max_interaction_length) +
173 " fm with the given timestep size.\n"
174 "If you have large timesteps please reduce them.\n"
175 "A larger box or the use of testparticles also helps.\n"
176 "Please take a look at your config.";
177 throw std::runtime_error(error_box_too_small);
185 if (
length_[i] >= max_interaction_length) {
190 index_factor[i] = std::nextafter(index_factor[i], 0.);
206 " cells. Therefore the Grid falls back to a single cell / "
210 if (include_unformed_particles) {
213 cells_.emplace_back(particles.copy_to_vector());
217 cells_.front().reserve(particles.size());
218 std::copy_if(particles.begin(), particles.end(),
219 std::back_inserter(
cells_.front()),
220 [&](
const ParticleData &
p) {
221 return p.xsec_scaling_factor(timestep_duration) > 0.0;
234 "\nindex_factor: ", index_factor);
245 auto &&cell_index_for = [&](
const ParticleData &
p) {
247 std::floor((
p.position()[1] - min_position[0]) * index_factor[0]),
248 std::floor((
p.position()[2] - min_position[1]) * index_factor[1]),
249 std::floor((
p.position()[3] - min_position[2]) * index_factor[2]));
251 for (
const auto &
p : particles) {
252 if (!include_unformed_particles &&
253 (
p.xsec_scaling_factor(timestep_duration) <= 0.0)) {
256 const auto idx = cell_index_for(
p);
261 "\nan out-of-bounds access would be necessary for the "
264 "\nfor a grid with the following parameters:\nmin: ", min_position,
266 "\nindex_factor: ", index_factor,
"\ncells_.size: ",
cells_.size(),
267 "\nrequested index: ", idx);
268 throw std::runtime_error(
"out-of-bounds grid access on construction");
int SizeType
A type to store the sizes.
const std::array< double, 3 > length_
The 3 lengths of the complete grid. Used for periodic boundary wrapping.
std::array< int, 3 > number_of_cells_
The number of cells in x, y, and z direction.
double cell_volume_
The volume of a single cell.
std::vector< ParticleList > cells_
The cell storage.
SizeType make_index(SizeType x, SizeType y, SizeType z) const
#define SMASH_SOURCE_LOCATION
Hackery that is required to output the location in the source code where the log statement occurs.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
@ ParticleNumber
Limit the number of cells to the number of particles.
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
@ Normal
Without ghost cells.
@ PeriodicBoundaries
With ghost cells for periodic boundaries.
static constexpr int LGrid
@ Largest
Make cells as large as possible.