ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
CellStructure.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
25
26#include "BoxGeometry.hpp"
27#include "LocalBox.hpp"
28#include "Particle.hpp"
29#include "ParticleList.hpp"
30#include "ParticleRange.hpp"
32#include "bond_error.hpp"
33#include "cell_system/Cell.hpp"
35#include "config/config.hpp"
36#include "ghosts.hpp"
37#include "system/Leaf.hpp"
38
39#include <utils/math/sqr.hpp>
40
41#include <boost/container/static_vector.hpp>
42#include <boost/iterator/indirect_iterator.hpp>
43#include <boost/range/algorithm/transform.hpp>
44
45#include <algorithm>
46#include <cassert>
47#include <iterator>
48#include <memory>
49#include <set>
50#include <stdexcept>
51#include <utility>
52#include <vector>
53
54namespace Cells {
55enum Resort : unsigned {
58 RESORT_GLOBAL = 2u
59};
60
61/**
62 * @brief Flags to select particle parts for communication.
63 */
64enum DataPart : unsigned {
65 DATA_PART_NONE = 0u, /**< Nothing */
66 DATA_PART_PROPERTIES = 1u, /**< Particle::p */
67 DATA_PART_POSITION = 2u, /**< Particle::r */
68 DATA_PART_MOMENTUM = 8u, /**< Particle::m */
69 DATA_PART_FORCE = 16u, /**< Particle::f */
70#ifdef BOND_CONSTRAINT
71 DATA_PART_RATTLE = 32u, /**< Particle::rattle */
72#endif
73 DATA_PART_BONDS = 64u /**< Particle::bonds */
74};
75} // namespace Cells
76
77/**
78 * @brief Map the data parts flags from cells to those
79 * used internally by the ghost communication.
80 *
81 * @param data_parts data parts flags
82 * @return ghost communication flags
83 */
84unsigned map_data_parts(unsigned data_parts);
85
86namespace Cells {
88 /* Find first non-empty cell */
89 auto first_non_empty =
90 std::find_if(cells.begin(), cells.end(),
91 [](const Cell *c) { return not c->particles().empty(); });
92
93 return {CellParticleIterator(first_non_empty, cells.end()),
94 CellParticleIterator(cells.end())};
95}
96} // namespace Cells
97
98/**
99 * @brief Distance vector and length handed to pair kernels.
100 */
101struct Distance {
103 : vec21(vec21), dist2(vec21.norm2()) {}
104
106 double dist2;
107};
108
109namespace detail {
110// NOLINTNEXTLINE(bugprone-exception-escape)
111struct MinimalImageDistance {
112 BoxGeometry const box;
113
114 Distance operator()(Particle const &p1, Particle const &p2) const {
115 return Distance(box.get_mi_vector(p1.pos(), p2.pos()));
116 }
117};
118
119struct EuclidianDistance {
120 Distance operator()(Particle const &p1, Particle const &p2) const {
121 return Distance(p1.pos() - p2.pos());
122 }
123};
124} // namespace detail
125
126/** Describes a cell structure / cell system. Contains information
127 * about the communication of cell contents (particles, ghosts, ...)
128 * between different nodes and the relation between particle
129 * positions and the cell system. All other properties of the cell
130 * system which are not common between different cell systems have to
131 * be stored in separate structures.
132 */
133struct CellStructure : public System::Leaf<CellStructure> {
134private:
135 /** The local id-to-particle index */
136 std::vector<Particle *> m_particle_index;
137 /** Implementation of the primary particle decomposition */
138 std::unique_ptr<ParticleDecomposition> m_decomposition;
139 /** Active type in m_decomposition */
141 /** One of @ref Cells::Resort, announces the level of resort needed.
142 */
143 unsigned m_resort_particles = Cells::RESORT_NONE;
144 bool m_rebuild_verlet_list = true;
145 std::vector<std::pair<Particle *, Particle *>> m_verlet_list;
146 double m_le_pos_offset_at_last_resort = 0.;
147 /** @brief Verlet list skin. */
148 double m_verlet_skin = 0.;
149 bool m_verlet_skin_set = false;
150 double m_verlet_reuse = 0.;
151
152public:
153 CellStructure(BoxGeometry const &box);
154
155 bool use_verlet_list = true;
156
157 /**
158 * @brief Update local particle index.
159 *
160 * Update the entry for a particle in the local particle
161 * index.
162 *
163 * @param id Entry to update.
164 * @param p Pointer to the particle.
165 */
167 assert(id >= 0);
168 // cppcheck-suppress assertWithSideEffect
169 assert(not p or p->id() == id);
170
171 if (static_cast<unsigned int>(id) >= m_particle_index.size())
172 m_particle_index.resize(static_cast<unsigned int>(id + 1));
173
174 m_particle_index[static_cast<unsigned int>(id)] = p;
175 }
176
177 /**
178 * @brief Update local particle index.
179 *
180 * Update the entry for a particle in the local particle
181 * index.
182 *
183 * @param p Pointer to the particle.
184 */
186 update_particle_index(p.id(), std::addressof(p));
187 }
188
189 /**
190 * @brief Update local particle index.
191 *
192 * @param pl List of particles whose index entries should be updated.
193 */
195 for (auto &p : pl) {
196 update_particle_index(p.id(), std::addressof(p));
197 }
198 }
199
200 /**
201 * @brief Clear the particles index.
202 */
203 void clear_particle_index() { m_particle_index.clear(); }
204
205private:
206 /**
207 * @brief Append a particle to a list and update this
208 * particle index accordingly.
209 * @param pl List to add the particle to.
210 * @param p Particle to add.
211 */
212 Particle &append_indexed_particle(ParticleList &pl, Particle &&p) {
213 /* Check if cell may reallocate, in which case the index
214 * entries for all particles in this cell have to be
215 * updated. */
216 auto const may_reallocate = pl.size() >= pl.capacity();
217 auto &new_part = pl.insert(std::move(p));
218
219 if (may_reallocate)
221 else {
222 update_particle_index(new_part);
223 }
224
225 return new_part;
226 }
227
228public:
229 /**
230 * @brief Get a local particle by id.
231 *
232 * @param id Particle to get.
233 * @return Pointer to particle if it is local,
234 * nullptr otherwise.
235 */
237 assert(id >= 0);
238
239 if (static_cast<unsigned int>(id) >= m_particle_index.size())
240 return nullptr;
241
242 return m_particle_index[static_cast<unsigned int>(id)];
243 }
244
245 /** @overload */
246 const Particle *get_local_particle(int id) const {
247 assert(id >= 0);
248
249 if (static_cast<unsigned int>(id) >= m_particle_index.size())
250 return nullptr;
251
252 return m_particle_index[static_cast<unsigned int>(id)];
253 }
254
255 template <class InputRange, class OutputIterator>
256 void get_local_particles(InputRange ids, OutputIterator out) {
257 boost::transform(ids, out,
258 [this](int id) { return get_local_particle(id); });
259 }
260
261 CellStructureType decomposition_type() const { return m_type; }
262
263 /** Maximal cutoff supported by current cell system. */
265
266 /** Maximal pair range supported by current cell system. */
268
270 return Cells::particles(decomposition().local_cells());
271 }
272
274 return Cells::particles(decomposition().ghost_cells());
275 }
276
277private:
278 /** Cell system dependent function to find the right cell for a
279 * particle.
280 * \param p Particle.
281 * \return pointer to cell where to put the particle, nullptr
282 * if the particle does not belong on this node.
283 */
284 Cell *particle_to_cell(const Particle &p) {
286 }
287 Cell const *particle_to_cell(const Particle &p) const {
289 }
290
291public:
292 /**
293 * @brief Add a particle.
294 *
295 * Moves a particle into the cell system. This adds
296 * a particle to the local node, irrespective of where
297 * it belongs.
298 *
299 * @param p Particle to add.
300 * @return Pointer to the particle in the cell
301 * system.
302 */
304
305 /**
306 * @brief Add a particle.
307 *
308 * Moves a particle into the cell system, if it
309 * belongs to this node. Otherwise this does not
310 * have an effect and the particle is discarded.
311 * This can be used to add a particle without
312 * knowledge where it should be placed by calling
313 * the function on all nodes, it will then add
314 * the particle in exactly one place.
315 *
316 * @param p Particle to add.
317 * @return Pointer to particle if it is local, null
318 * otherwise.
319 */
321
322 /**
323 * @brief Remove a particle.
324 *
325 * Removes a particle and all bonds pointing
326 * to it. This is a collective call.
327 *
328 * @param id Id of particle to remove.
329 */
330 void remove_particle(int id);
331
332 /**
333 * @brief Get the maximal particle id on this node.
334 *
335 * This returns the highest particle id on
336 * this node, or -1 if there are no particles on this node.
337 */
338 int get_max_local_particle_id() const;
339
340 /**
341 * @brief Remove all particles from the cell system.
342 *
343 * This allows linear time removal of all particles from
344 * the system, removing each particle individually would
345 * be quadratic.
346 */
348
349 /**
350 * @brief Get the underlying particle decomposition.
351 *
352 * Should be used solely for informative purposes.
353 *
354 * @return The active particle decomposition.
355 */
357 return assert(m_decomposition), *m_decomposition;
358 }
359
360private:
362 return assert(m_decomposition), *m_decomposition;
363 }
364
365public:
366 /**
367 * @brief Increase the local resort level at least to @p level.
368 */
370 m_resort_particles |= level;
371 assert(m_resort_particles >= level);
372 }
373
374 /**
375 * @brief Get the currently scheduled resort level.
376 */
377 unsigned get_resort_particles() const { return m_resort_particles; }
378
379 /**
380 * @brief Set the resort level to sorted.
381 */
382 void clear_resort_particles() { m_resort_particles = Cells::RESORT_NONE; }
383
384 /**
385 * @brief Check whether a particle has moved further than half the skin
386 * since the last Verlet list update, thus requiring a resort.
387 * @param additional_offset Offset which is added to the distance the
388 * particle has travelled when comparing to half
389 * the Verlet skin (e.g., for Lees-Edwards BC).
390 * @return Whether a resort is needed.
391 */
392 bool
393 check_resort_required(Utils::Vector3d const &additional_offset = {}) const {
394 auto const particles = local_particles();
395 auto const lim = Utils::sqr(m_verlet_skin / 2.) - additional_offset.norm2();
396 return std::any_of(
397 particles.begin(), particles.end(), [lim](const auto &p) {
398 return ((p.pos() - p.pos_at_last_verlet_update()).norm2() > lim);
399 });
400 }
401
403 return m_le_pos_offset_at_last_resort;
404 }
405
406 /**
407 * @brief Synchronize number of ghosts.
408 */
409 void ghosts_count();
410
411 /**
412 * @brief Update ghost particles.
413 *
414 * Update ghost particles with data from the real particles.
415 *
416 * @param data_parts Particle parts to update, combination of @ref
417 * Cells::DataPart
418 */
419 void ghosts_update(unsigned data_parts);
420
421 /**
422 * @brief Update ghost particles, with particle resort if needed.
423 *
424 * Update ghost particles with data from the real particles.
425 * Resort particles if a resort is due.
426 *
427 * @param data_parts Particle parts to update, combination of @ref
428 * Cells::DataPart
429 */
430 void update_ghosts_and_resort_particle(unsigned data_parts);
431
432 /**
433 * @brief Add forces from ghost particles to real particles.
434 */
436
437#ifdef BOND_CONSTRAINT
438 /**
439 * @brief Add rattle corrections from ghost particles to real particles.
440 */
442#endif
443
444 /**
445 * @brief Resort particles.
446 */
447 void resort_particles(bool global_flag);
448
449 /** @brief Whether the Verlet skin is set. */
450 auto is_verlet_skin_set() const { return m_verlet_skin_set; }
451
452 /** @brief Get the Verlet skin. */
453 auto get_verlet_skin() const { return m_verlet_skin; }
454
455 /** @brief Set the Verlet skin. */
456 void set_verlet_skin(double value);
457
458 /** @brief Set the Verlet skin using a heuristic. */
460
461 void update_verlet_stats(int n_steps, int n_verlet_updates) {
462 if (n_verlet_updates > 0) {
463 m_verlet_reuse = n_steps / static_cast<double>(n_verlet_updates);
464 } else {
465 m_verlet_reuse = 0.;
466 }
467 }
468
469 /** @brief Average number of integration steps the Verlet list was re-used */
470 auto get_verlet_reuse() const { return m_verlet_reuse; }
471
472private:
473 /**
474 * @brief Resolve ids to particles.
475 *
476 * @throws BondResolutionError if one of the ids
477 * was not found.
478 *
479 * @param partner_ids Ids to resolve.
480 * @return Vector of Particle pointers.
481 */
482 auto resolve_bond_partners(Utils::Span<const int> partner_ids) {
483 boost::container::static_vector<Particle *, 4> partners;
484 get_local_particles(partner_ids, std::back_inserter(partners));
485
486 /* Check if id resolution failed for any partner */
487 if (std::any_of(partners.begin(), partners.end(),
488 [](Particle const *const p) { return p == nullptr; })) {
489 throw BondResolutionError{};
490 }
491
492 return partners;
493 }
494
495 /**
496 * @brief Execute kernel for every bond on particle.
497 * @tparam Handler Callable, which can be invoked with
498 * (Particle, int, Utils::Span<Particle *>),
499 * returning a bool.
500 * @param p Particles for whom the bonds are evaluated.
501 * @param handler is called for every bond, and handed
502 * p, the bond id and a span with the bond
503 * partners as arguments. Its return value
504 * should indicate if the bond was broken.
505 */
506 template <class Handler>
507 void execute_bond_handler(Particle &p, Handler handler) {
508 for (const BondView bond : p.bonds()) {
509 auto const partner_ids = bond.partner_ids();
510
511 try {
512 auto partners = resolve_bond_partners(partner_ids);
513
514 auto const bond_broken =
515 handler(p, bond.bond_id(), Utils::make_span(partners));
516
517 if (bond_broken) {
518 bond_broken_error(p.id(), partner_ids);
519 }
520 } catch (const BondResolutionError &) {
521 bond_broken_error(p.id(), partner_ids);
522 }
523 }
524 }
525
526 /**
527 * @brief Go through ghost cells and remove the ghost entries from the
528 * local particle index.
529 */
530 void invalidate_ghosts() {
531 for (auto const &p : ghost_particles()) {
532 if (get_local_particle(p.id()) == &p) {
533 update_particle_index(p.id(), nullptr);
534 }
535 }
536 }
537
538 /** @brief Set the particle decomposition, keeping the particles. */
539 void set_particle_decomposition(
540 std::unique_ptr<ParticleDecomposition> &&decomposition) {
542
543 /* Swap in new cell system */
544 std::swap(m_decomposition, decomposition);
545
546 /* Add particles to new system */
547 for (auto &p : Cells::particles(decomposition->local_cells())) {
548 add_particle(std::move(p));
549 }
550 }
551
552public:
553 /**
554 * @brief Set the particle decomposition to @ref AtomDecomposition.
555 */
557
558 /**
559 * @brief Set the particle decomposition to @ref RegularDecomposition.
560 *
561 * @param range Interaction range.
562 */
563 void set_regular_decomposition(double range);
564
565 /**
566 * @brief Set the particle decomposition to @ref HybridDecomposition.
567 *
568 * @param cutoff_regular Interaction cutoff_regular.
569 * @param n_square_types Particle types to put into n_square decomposition.
570 */
571 void set_hybrid_decomposition(double cutoff_regular,
572 std::set<int> n_square_types);
573
574private:
575 /**
576 * @brief Run link_cell algorithm for local cells.
577 *
578 * @tparam Kernel Needs to be callable with (Particle, Particle, Distance).
579 * @param kernel Pair kernel functor.
580 */
581 template <class Kernel> void link_cell(Kernel kernel) {
582 auto const maybe_box = decomposition().minimum_image_distance();
583 auto const local_cells_span = decomposition().local_cells();
584 auto const first = boost::make_indirect_iterator(local_cells_span.begin());
585 auto const last = boost::make_indirect_iterator(local_cells_span.end());
586
587 if (maybe_box) {
589 first, last,
590 [&kernel, df = detail::MinimalImageDistance{decomposition().box()}](
591 Particle &p1, Particle &p2) { kernel(p1, p2, df(p1, p2)); });
592 } else {
593 if (decomposition().box().type() != BoxType::CUBOID) {
594 throw std::runtime_error("Non-cuboid box type is not compatible with a "
595 "particle decomposition that relies on "
596 "EuclideanDistance for distance calculation.");
597 }
599 first, last,
600 [&kernel, df = detail::EuclidianDistance{}](
601 Particle &p1, Particle &p2) { kernel(p1, p2, df(p1, p2)); });
602 }
603 }
604
605 /** Non-bonded pair loop with verlet lists.
606 *
607 * @param pair_kernel Kernel to apply
608 * @param verlet_criterion Filter for verlet lists.
609 */
610 template <class PairKernel, class VerletCriterion>
611 void verlet_list_loop(PairKernel pair_kernel,
612 const VerletCriterion &verlet_criterion) {
613 /* In this case the verlet list update is attached to
614 * the pair kernel, and the verlet list is rebuilt as
615 * we go. */
616 if (m_rebuild_verlet_list) {
617 m_verlet_list.clear();
618
619 link_cell([&](Particle &p1, Particle &p2, Distance const &d) {
620 if (verlet_criterion(p1, p2, d)) {
621 m_verlet_list.emplace_back(&p1, &p2);
622 pair_kernel(p1, p2, d);
623 }
624 });
625
626 m_rebuild_verlet_list = false;
627 } else {
628 auto const maybe_box = decomposition().minimum_image_distance();
629 /* In this case the pair kernel is just run over the verlet list. */
630 if (maybe_box) {
631 auto const distance_function =
632 detail::MinimalImageDistance{decomposition().box()};
633 for (auto &pair : m_verlet_list) {
634 pair_kernel(*pair.first, *pair.second,
635 distance_function(*pair.first, *pair.second));
636 }
637 } else {
638 auto const distance_function = detail::EuclidianDistance{};
639 for (auto &pair : m_verlet_list) {
640 pair_kernel(*pair.first, *pair.second,
641 distance_function(*pair.first, *pair.second));
642 }
643 }
644 }
645 }
646
647public:
648 /** Bonded pair loop.
649 * @param bond_kernel Kernel to apply
650 */
651 template <class BondKernel> void bond_loop(BondKernel const &bond_kernel) {
652 for (auto &p : local_particles()) {
653 execute_bond_handler(p, bond_kernel);
654 }
655 }
656
657 /** Non-bonded pair loop.
658 * @param pair_kernel Kernel to apply
659 */
660 template <class PairKernel> void non_bonded_loop(PairKernel pair_kernel) {
661 link_cell(pair_kernel);
662 }
663
664 /** Non-bonded pair loop with potential use
665 * of verlet lists.
666 * @param pair_kernel Kernel to apply
667 * @param verlet_criterion Filter for verlet lists.
668 */
669 template <class PairKernel, class VerletCriterion>
670 void non_bonded_loop(PairKernel pair_kernel,
671 const VerletCriterion &verlet_criterion) {
672 if (use_verlet_list) {
673 verlet_list_loop(pair_kernel, verlet_criterion);
674 } else {
675 /* No verlet lists, just run the kernel with pairs from the cells. */
676 link_cell(pair_kernel);
677 }
678 }
679
680 /**
681 * @brief Check that particle index is commensurate with particles.
682 *
683 * For each local particles is checked that has a correct entry
684 * in the particles index, and that there are no excess (non-existing)
685 * particles in the index.
686 */
687 void check_particle_index() const;
688
689 /**
690 * @brief Check that particles are in the correct cell.
691 *
692 * This checks for all local particles that the result
693 * of particles_to_cell is the cell the particles is
694 * actually in, e.g. that the particles are sorted according
695 * to particles_to_cell.
696 */
697 void check_particle_sorting() const;
698
699public:
700 /**
701 * @brief Find cell a particle is stored in.
702 *
703 * For local particles, this returns the cell they
704 * are stored in, otherwise nullptr is returned.
705 *
706 * @param p Particle to find cell for
707 * @return Cell for particle or nullptr.
708 */
710 assert(not get_resort_particles());
711
712 if (p.is_ghost()) {
713 return nullptr;
714 }
715
716 return particle_to_cell(p);
717 }
718
719 /**
720 * @brief Run kernel on all particles inside local cell and its neighbors.
721 *
722 * @param p Particle to find cell for
723 * @param kernel Function with signature <tt>double(Particle const&,
724 * Particle const&, Utils::Vector3d const&)</tt>
725 * @return false if cell is not found, otherwise true
726 */
727 template <class Kernel>
729 Kernel &kernel) {
730 auto const cell = find_current_cell(p);
731
732 if (cell == nullptr) {
733 return false;
734 }
735
736 auto const maybe_box = decomposition().minimum_image_distance();
737
738 if (maybe_box) {
739 auto const distance_function =
740 detail::MinimalImageDistance{decomposition().box()};
741 short_range_neighbor_loop(p, cell, kernel, distance_function);
742 } else {
743 auto const distance_function = detail::EuclidianDistance{};
744 short_range_neighbor_loop(p, cell, kernel, distance_function);
745 }
746 return true;
747 }
748
749private:
750 template <class Kernel, class DistanceFunc>
751 void short_range_neighbor_loop(Particle const &p1, Cell *const cell,
752 Kernel &kernel, DistanceFunc const &df) {
753 /* Iterate over particles inside cell */
754 for (auto const &p2 : cell->particles()) {
755 if (p1.id() != p2.id()) {
756 auto const vec = df(p1, p2).vec21;
757 kernel(p1, p2, vec);
758 }
759 }
760 /* Iterate over all neighbors */
761 for (auto const neighbor : cell->neighbors().all()) {
762 /* Iterate over particles in neighbors */
763 if (neighbor != cell) {
764 for (auto const &p2 : neighbor->particles()) {
765 auto const vec = df(p1, p2).vec21;
766 kernel(p1, p2, vec);
767 }
768 }
769 }
770 }
771};
ParticleIterator< Cell *const * > CellParticleIterator
CellStructureType
Cell structure topology.
@ NSQUARE
Atom decomposition (N-square).
unsigned map_data_parts(unsigned data_parts)
Map the data parts flags from cells to those used internally by the ghost communication.
float u[3]
void bond_broken_error(int id, Utils::Span< const int > partner_ids)
Immutable view on a bond.
Definition BondList.hpp:45
BoxType type() const
Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
Definition Cell.hpp:98
A distributed particle decomposition.
virtual Utils::Span< Cell *const > local_cells() const =0
Get pointer to local cells.
virtual Utils::Vector3d max_cutoff() const =0
Maximum supported cutoff.
virtual Cell * particle_to_cell(Particle const &p)=0
Determine which cell a particle id belongs to.
virtual Utils::Vector3d max_range() const =0
Range in which calculations are performed.
virtual BoxGeometry const & box() const =0
virtual boost::optional< BoxGeometry > minimum_image_distance() const =0
Return the box geometry needed for distance calculation if minimum image convention should be used ne...
A range of particles.
Abstract class that represents a component of the system.
std::size_t capacity() const
Capacity of the container.
Definition Bag.hpp:104
T & insert(T const &v)
Insert an element into the container.
Definition Bag.hpp:147
std::size_t size() const
Number of elements in the container.
Definition Bag.hpp:90
A stripped-down version of std::span from C++17.
Definition Span.hpp:38
DEVICE_QUALIFIER constexpr iterator end() const
Definition Span.hpp:91
DEVICE_QUALIFIER constexpr iterator begin() const
Definition Span.hpp:89
Returns true if the particles are to be considered for short range interactions.
This file contains the defaults for ESPResSo.
Ghost particles and particle exchange.
void link_cell(CellIterator first, CellIterator last, PairKernel &&pair_kernel)
Iterates over all particles in the cell range, and over all pairs within the cells and with their nei...
Definition link_cell.hpp:32
DataPart
Flags to select particle parts for communication.
@ DATA_PART_MOMENTUM
Particle::m.
@ DATA_PART_FORCE
Particle::f.
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_BONDS
Particle::bonds.
@ DATA_PART_NONE
Nothing.
@ DATA_PART_RATTLE
Particle::rattle.
@ DATA_PART_POSITION
Particle::r.
ParticleRange particles(Utils::Span< Cell *const > cells)
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
DEVICE_QUALIFIER constexpr Span< T > make_span(T *p, std::size_t N)
Definition Span.hpp:112
auto constexpr new_part
Exception indicating that a particle id could not be resolved.
Describes a cell structure / cell system.
ParticleRange ghost_particles() const
Particle * get_local_particle(int id)
Get a local particle by id.
void update_particle_index(ParticleList &pl)
Update local particle index.
void check_particle_sorting() const
Check that particles are in the correct cell.
void set_regular_decomposition(double range)
Set the particle decomposition to RegularDecomposition.
void clear_resort_particles()
Set the resort level to sorted.
Cell * find_current_cell(const Particle &p)
Find cell a particle is stored in.
auto is_verlet_skin_set() const
Whether the Verlet skin is set.
ParticleDecomposition const & decomposition() const
Get the underlying particle decomposition.
void clear_particle_index()
Clear the particles index.
void update_ghosts_and_resort_particle(unsigned data_parts)
Update ghost particles, with particle resort if needed.
Particle * add_local_particle(Particle &&p)
Add a particle.
void set_verlet_skin_heuristic()
Set the Verlet skin using a heuristic.
void set_verlet_skin(double value)
Set the Verlet skin.
void ghosts_update(unsigned data_parts)
Update ghost particles.
auto get_le_pos_offset_at_last_resort() const
void get_local_particles(InputRange ids, OutputIterator out)
void update_verlet_stats(int n_steps, int n_verlet_updates)
void update_particle_index(int id, Particle *p)
Update local particle index.
void ghosts_reduce_forces()
Add forces from ghost particles to real particles.
unsigned get_resort_particles() const
Get the currently scheduled resort level.
auto get_verlet_reuse() const
Average number of integration steps the Verlet list was re-used.
void non_bonded_loop(PairKernel pair_kernel)
Non-bonded pair loop.
Utils::Vector3d max_range() const
Maximal pair range supported by current cell system.
bool check_resort_required(Utils::Vector3d const &additional_offset={}) const
Check whether a particle has moved further than half the skin since the last Verlet list update,...
const Particle * get_local_particle(int id) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
void bond_loop(BondKernel const &bond_kernel)
Bonded pair loop.
void ghosts_count()
Synchronize number of ghosts.
void set_resort_particles(Cells::Resort level)
Increase the local resort level at least to level.
void remove_particle(int id)
Remove a particle.
Particle * add_particle(Particle &&p)
Add a particle.
void resort_particles(bool global_flag)
Resort particles.
void check_particle_index() const
Check that particle index is commensurate with particles.
auto get_verlet_skin() const
Get the Verlet skin.
void set_atom_decomposition()
Set the particle decomposition to AtomDecomposition.
bool run_on_particle_short_range_neighbors(Particle const &p, Kernel &kernel)
Run kernel on all particles inside local cell and its neighbors.
void remove_all_particles()
Remove all particles from the cell system.
ParticleRange local_particles() const
void update_particle_index(Particle &p)
Update local particle index.
void ghosts_reduce_rattle_correction()
Add rattle corrections from ghost particles to real particles.
CellStructureType decomposition_type() const
void set_hybrid_decomposition(double cutoff_regular, std::set< int > n_square_types)
Set the particle decomposition to HybridDecomposition.
int get_max_local_particle_id() const
Get the maximal particle id on this node.
Utils::Vector3d max_cutoff() const
Maximal cutoff supported by current cell system.
void non_bonded_loop(PairKernel pair_kernel, const VerletCriterion &verlet_criterion)
Non-bonded pair loop with potential use of verlet lists.
Distance vector and length handed to pair kernels.
Utils::Vector3d vec21
Distance(Utils::Vector3d const &vec21)
Struct holding all information for one particle.
Definition Particle.hpp:393
bool is_ghost() const
Definition Particle.hpp:438
auto const & pos() const
Definition Particle.hpp:429
auto const & id() const
Definition Particle.hpp:412