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 std::numeric_limits<int>::max() / index_factor[i])) {
158 throw std::overflow_error(
159 "An integer overflow would occur constructing the system grid.\n"
160 "Impossible to (further) simulate the provided system using "
162 "Refer to the user guide for more information (see the Modi "
166 static_cast<int>(std::floor(
length_[i] * index_factor[i]));
178 std::string error_box_too_small =
179 "Input error: With the chosen time step (Delta_Time), your box is\n"
180 "too small for the grid. Using the provided time step, the minimal\n"
181 "length of the box should be " +
182 std::to_string(2 * max_interaction_length) +
183 "fm. Using a smaller time step\n"
184 "will reduce the minimal needed box size. The use of test particles\n"
185 "also helps reducing the minimum needed size. Have a look to the\n"
186 "user guide (e.g. box modus page) for further information.\n"
187 "Please, adjust your config file and run SMASH again.";
188 throw std::runtime_error(error_box_too_small);
196 if (
length_[i] >= max_interaction_length) {
201 index_factor[i] = std::nextafter(index_factor[i], 0.);
217 " cells. Therefore the Grid falls back to a single cell / "
221 if (include_unformed_particles) {
224 cells_.emplace_back(particles.copy_to_vector());
228 cells_.front().reserve(particles.size());
229 std::copy_if(particles.begin(), particles.end(),
230 std::back_inserter(
cells_.front()),
231 [&](
const ParticleData &
p) {
232 return p.xsec_scaling_factor(timestep_duration) > 0.0;
245 "\nindex_factor: ", index_factor);
256 auto &&cell_index_for = [&](
const ParticleData &
p) {
258 std::floor((
p.position()[1] - min_position[0]) * index_factor[0]),
259 std::floor((
p.position()[2] - min_position[1]) * index_factor[1]),
260 std::floor((
p.position()[3] - min_position[2]) * index_factor[2]));
262 for (
const auto &
p : particles) {
263 if (!include_unformed_particles &&
264 (
p.xsec_scaling_factor(timestep_duration) <= 0.0)) {
267 const auto idx = cell_index_for(
p);
272 "\nan out-of-bounds access would be necessary for the "
275 "\nfor a grid with the following parameters:\nmin: ", min_position,
277 "\nindex_factor: ", index_factor,
"\ncells_.size: ",
cells_.size(),
278 "\nrequested index: ", idx);
279 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.
#define unlikely(x)
Tell the branch predictor that this expression is likely false.
@ 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.