deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
particle_accessor.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2017 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_particles_particle_accessor_h
14#define dealii_particles_particle_accessor_h
15
16#include <deal.II/base/config.h>
17
19
20#include <deal.II/grid/tria.h>
22
25
26#include <boost/geometry/index/indexable.hpp>
27#include <boost/serialization/array_wrapper.hpp>
28
29#include <list>
30
31
33
34namespace Particles
35{
36 // Forward declarations
37#ifndef DOXYGEN
38 template <int, int>
39 class ParticleIterator;
40 template <int, int>
41 class ParticleHandler;
42#endif
43
47 template <int dim, int spacedim = dim>
49 {
50 public:
85 {
89 ParticlesInCell() = default;
90
101
105 std::vector<typename PropertyPool<dim, spacedim>::Handle> particles;
106
111 };
112
116 using particle_container = std::list<ParticlesInCell>;
117
121 void *
123
124
128 const void *
130
151 void
152 set_location(const Point<spacedim> &new_location);
153
159 const Point<spacedim> &
161
185
206 void
207 set_reference_location(const Point<dim> &new_reference_location);
208
212 const Point<dim> &
214
218 void
220
225 get_id() const;
226
247
252 bool
254
275 void
276 set_properties(const std::vector<double> &new_properties);
277
298 void
300
324 void
325 set_properties(const Tensor<1, dim> &new_properties);
326
334 {
335 // The implementation is up here inside the class declaration because
336 // NVCC (at least in 12.5 and 12.6) otherwise produce a compile error:
337 //
338 // error: no declaration matches ‘::ArrayView<__remove_cv(const
339 // double)> ::Particles::ParticleAccessor<dim,
340 // spacedim>::get_properties()’
341 //
342 // See https://github.com/dealii/dealii/issues/17148
344
346 }
347
348
356
362 std::size_t
364
370
376 template <class Archive>
377 void
378 save(Archive &ar, const unsigned int version) const;
379
385 template <class Archive>
386 void
387 load(Archive &ar, const unsigned int version);
388
389#ifdef DOXYGEN
395 template <class Archive>
396 void
397 serialize(Archive &archive, const unsigned int version);
398#else
399 // This macro defines the serialize() method that is compatible with
400 // the templated save() and load() method that have been implemented.
401 BOOST_SERIALIZATION_SPLIT_MEMBER()
402#endif
403
407 void
409
413 void
415
419 bool
421
425 bool
427
432 state() const;
433
434 private:
439
447 const typename particle_container::iterator particles_in_cell,
449 const unsigned int particle_index_within_cell);
450
457 get_handle() const;
458
464
469 typename particle_container::iterator particles_in_cell;
470
475
480
481 // Make ParticleIterator a friend to allow it constructing
482 // ParticleAccessors.
483 template <int, int>
484 friend class ParticleIterator;
485 template <int, int>
486 friend class ParticleHandler;
487 };
488
489
490
491 template <int dim, int spacedim>
492 template <class Archive>
493 inline void
494 ParticleAccessor<dim, spacedim>::load(Archive &ar, const unsigned int)
495 {
496 unsigned int n_properties = 0;
497
498 Point<spacedim> location;
499 Point<dim> reference_location;
501 ar &location &reference_location &id &n_properties;
502
503 set_location(location);
504 set_reference_location(reference_location);
505 set_id(id);
506
507 if (n_properties > 0)
508 {
509 ArrayView<double> properties(get_properties());
510 Assert(
511 properties.size() == n_properties,
513 "This particle was serialized with " +
514 std::to_string(n_properties) +
515 " properties, but the new property handler provides space for " +
516 std::to_string(properties.size()) +
517 " properties. Deserializing a particle only works for matching property sizes."));
518
519 ar &boost::serialization::make_array(properties.data(), n_properties);
520 }
521 }
522
523
524
525 template <int dim, int spacedim>
526 template <class Archive>
527 inline void
528 ParticleAccessor<dim, spacedim>::save(Archive &ar, const unsigned int) const
529 {
530 unsigned int n_properties = 0;
531 if ((property_pool != nullptr) &&
533 n_properties = get_properties().size();
534
535 Point<spacedim> location = get_location();
536 Point<dim> reference_location = get_reference_location();
537 types::particle_index id = get_id();
538
539 ar &location &reference_location &id &n_properties;
540
541 if (n_properties > 0)
542 ar &boost::serialization::make_array(get_properties().data(),
543 n_properties);
544 }
545
546
547 // ------------------------- inline functions ------------------------------
548
549 template <int dim, int spacedim>
551 : particles_in_cell(typename particle_container::iterator())
552 , property_pool(nullptr)
553 , particle_index_within_cell(numbers::invalid_unsigned_int)
554 {}
555
556
557
558 template <int dim, int spacedim>
560 const typename particle_container::iterator particles_in_cell,
561 const PropertyPool<dim, spacedim> &property_pool,
562 const unsigned int particle_index_within_cell)
563 : particles_in_cell(particles_in_cell)
564 , property_pool(const_cast<PropertyPool<dim, spacedim> *>(&property_pool))
565 , particle_index_within_cell(particle_index_within_cell)
566 {}
567
568
569
570 template <int dim, int spacedim>
571 inline const void *
573 const void *data)
574 {
576
577 const types::particle_index *id_data =
578 static_cast<const types::particle_index *>(data);
579 set_id(*id_data++);
580 const double *pdata = reinterpret_cast<const double *>(id_data);
581
582 Point<spacedim> location;
583 for (unsigned int i = 0; i < spacedim; ++i)
584 location[i] = *pdata++;
585 set_location(location);
586
587 Point<dim> reference_location;
588 for (unsigned int i = 0; i < dim; ++i)
589 reference_location[i] = *pdata++;
590 set_reference_location(reference_location);
591
592 // See if there are properties to load
593 if (has_properties())
594 {
595 const ArrayView<double> particle_properties =
596 property_pool->get_properties(get_handle());
597 const unsigned int size = particle_properties.size();
598 for (unsigned int i = 0; i < size; ++i)
599 particle_properties[i] = *pdata++;
600 }
601
602 return static_cast<const void *>(pdata);
603 }
604
605
606
607 template <int dim, int spacedim>
608 inline void *
610 void *data) const
611 {
613
614 types::particle_index *id_data = static_cast<types::particle_index *>(data);
615 *id_data = get_id();
616 ++id_data;
617 double *pdata = reinterpret_cast<double *>(id_data);
618
619 // Write location
620 for (unsigned int i = 0; i < spacedim; ++i, ++pdata)
621 *pdata = get_location()[i];
622
623 // Write reference location
624 for (unsigned int i = 0; i < dim; ++i, ++pdata)
625 *pdata = get_reference_location()[i];
626
627 // Write properties
628 if (has_properties())
629 {
630 const ArrayView<double> particle_properties =
631 property_pool->get_properties(get_handle());
632 for (unsigned int i = 0; i < particle_properties.size(); ++i, ++pdata)
633 *pdata = particle_properties[i];
634 }
635
636 return static_cast<void *>(pdata);
637 }
638
639
640
641 template <int dim, int spacedim>
642 inline void
644 {
646
647 property_pool->set_location(get_handle(), new_loc);
648 }
649
650
651
652 template <int dim, int spacedim>
653 inline const Point<spacedim> &
655 {
657
658 return property_pool->get_location(get_handle());
659 }
660
661
662
663 template <int dim, int spacedim>
664 inline Point<spacedim> &
666 {
668
669 return property_pool->get_location(get_handle());
670 }
671
672
673
674 template <int dim, int spacedim>
675 inline void
677 const Point<dim> &new_loc)
678 {
680
681 property_pool->set_reference_location(get_handle(), new_loc);
682 }
683
684
685
686 template <int dim, int spacedim>
687 inline const Point<dim> &
689 {
691
692 return property_pool->get_reference_location(get_handle());
693 }
694
695
696
697 template <int dim, int spacedim>
700 {
702
703 return property_pool->get_id(get_handle());
704 }
705
706
707
708 template <int dim, int spacedim>
711 {
713
714 return get_handle();
715 }
716
717
718
719 template <int dim, int spacedim>
720 inline void
722 {
724
725 property_pool->set_id(get_handle(), new_id);
726 }
727
728
729
730 template <int dim, int spacedim>
731 inline bool
733 {
735
736 // Particles always have a property pool associated with them,
737 // but we can access properties only if there is a valid handle.
738 // The only way a particle can have no valid handle if it has
739 // been moved-from -- but that leaves an object in an invalid
740 // state, and so we can just assert that that can't be the case.
743 return (property_pool->n_properties_per_slot() > 0);
744 }
745
746
747
748 template <int dim, int spacedim>
749 inline void
751 const std::vector<double> &new_properties)
752 {
754
755 set_properties(
756 ArrayView<const double>(new_properties.data(), new_properties.size()));
757 }
758
759
760
761 template <int dim, int spacedim>
762 inline void
764 const ArrayView<const double> &new_properties)
765 {
767
768 const ArrayView<double> property_values =
769 property_pool->get_properties(get_handle());
770
771 Assert(new_properties.size() == property_values.size(),
773 "You are trying to assign properties with an incompatible length. "
774 "The particle has space to store " +
775 std::to_string(property_values.size()) +
776 " properties, but you are trying to assign " +
777 std::to_string(new_properties.size()) +
778 " properties. This is not allowed."));
779
780 if (property_values.size() > 0)
781 std::copy(new_properties.begin(),
782 new_properties.end(),
783 property_values.begin());
784 }
785
786
787
788 template <int dim, int spacedim>
789 inline void
791 const Tensor<1, dim> &new_properties)
792 {
794
795 // A Tensor object is not an array, so we cannot just create an
796 // ArrayView object for it. Rather, copy the data into a true
797 // array and make the ArrayView from that.
798 double array[dim];
799 for (unsigned int d = 0; d < dim; ++d)
800 array[d] = new_properties[d];
801
802 set_properties(make_array_view(array));
803 }
804
805
806
807 template <int dim, int spacedim>
810 {
812
813 return property_pool->get_properties(get_handle());
814 }
815
816
817
818 template <int dim, int spacedim>
819 inline const typename Triangulation<dim, spacedim>::cell_iterator &
821 {
823 Assert(particles_in_cell->cell.state() == IteratorState::valid,
825
826 return particles_in_cell->cell;
827 }
828
829
830
831 // template <int dim, int spacedim>
832 // inline ArrayView<double>
833 // ParticleAccessor<dim, spacedim>::get_properties()
834
835
836
837 template <int dim, int spacedim>
838 inline std::size_t
840 {
842
843 std::size_t size = sizeof(get_id()) +
844 sizeof(double) * spacedim + // get_location()
845 sizeof(double) * dim; // get_reference_location()
846
847 if (has_properties())
848 {
849 size += sizeof(double) * get_properties().size();
850 }
851 return size;
852 }
853
854
855
856 template <int dim, int spacedim>
857 inline void
859 {
861
862 ++particle_index_within_cell;
863
864 if (particle_index_within_cell >= particles_in_cell->particles.size())
865 {
866 particle_index_within_cell = 0;
867 ++particles_in_cell;
868 }
869 }
870
871
872
873 template <int dim, int spacedim>
874 inline void
876 {
878
879 if (particle_index_within_cell > 0)
880 --particle_index_within_cell;
881 else
882 {
883 --particles_in_cell;
884 particle_index_within_cell = particles_in_cell->particles.empty() ?
885 0 :
886 particles_in_cell->particles.size() - 1;
887 }
888 }
889
890
891
892 template <int dim, int spacedim>
893 inline bool
895 const ParticleAccessor<dim, spacedim> &other) const
896 {
897 return !(*this == other);
898 }
899
900
901
902 template <int dim, int spacedim>
903 inline bool
905 const ParticleAccessor<dim, spacedim> &other) const
906 {
907 return (property_pool == other.property_pool) &&
908 (particles_in_cell == other.particles_in_cell) &&
909 (particle_index_within_cell == other.particle_index_within_cell);
910 }
911
912
913
914 template <int dim, int spacedim>
917 {
918 if (property_pool != nullptr &&
919 particles_in_cell->cell.state() == IteratorState::valid &&
920 particle_index_within_cell < particles_in_cell->particles.size())
922 else if (property_pool != nullptr &&
923 particles_in_cell->cell.state() == IteratorState::past_the_end &&
924 particle_index_within_cell == 0)
926 else
928
930 }
931
932
933
934 template <int dim, int spacedim>
937 {
938 return particles_in_cell->particles[particle_index_within_cell];
939 }
940
941
942
943 template <int dim, int spacedim>
944 inline const typename PropertyPool<dim, spacedim>::Handle &
946 {
947 return particles_in_cell->particles[particle_index_within_cell];
948 }
949
950} // namespace Particles
951
953
954namespace boost
955{
956 namespace geometry
957 {
958 namespace index
959 {
964 template <int dim, int spacedim>
965 struct indexable<::Particles::ParticleAccessor<dim, spacedim>>
966 {
971 using result_type = const ::Point<spacedim> &;
972
974 operator()(const ::Particles::ParticleAccessor<dim, spacedim>
975 &accessor) const
976 {
977 return accessor.get_location();
978 }
979 };
980 } // namespace index
981 } // namespace geometry
982} // namespace boost
983
984#endif
*  *  iterator()=default
ArrayView< std::remove_reference_t< typename std::iterator_traits< Iterator >::reference >, MemorySpaceType > make_array_view(const Iterator begin, const Iterator end)
iterator begin() const
Definition array_view.h:755
iterator end() const
Definition array_view.h:764
value_type * data() const noexcept
Definition array_view.h:714
std::size_t size() const
Definition array_view.h:737
particle_container::iterator particles_in_cell
const Point< spacedim > & get_location() const
types::particle_index get_id() const
void save(Archive &ar, const unsigned int version) const
types::particle_index get_local_index() const
std::list< ParticlesInCell > particle_container
const void * read_particle_data_from_memory(const void *data)
void load(Archive &ar, const unsigned int version)
const Triangulation< dim, spacedim >::cell_iterator & get_surrounding_cell() const
IteratorState::IteratorStates state() const
bool operator!=(const ParticleAccessor< dim, spacedim > &other) const
void set_properties(const Tensor< 1, dim > &new_properties)
void set_location(const Point< spacedim > &new_location)
PropertyPool< dim, spacedim >::Handle & get_handle()
void serialize(Archive &archive, const unsigned int version)
ArrayView< double > get_properties()
void set_reference_location(const Point< dim > &new_reference_location)
const Point< dim > & get_reference_location() const
std::size_t serialized_size_in_bytes() const
const PropertyPool< dim, spacedim >::Handle & get_handle() const
void set_properties(const std::vector< double > &new_properties)
Point< spacedim > & get_location()
ParticleAccessor(const typename particle_container::iterator particles_in_cell, const PropertyPool< dim, spacedim > &property_pool, const unsigned int particle_index_within_cell)
PropertyPool< dim, spacedim > * property_pool
void * write_particle_data_to_memory(void *data) const
void set_properties(const ArrayView< const double > &new_properties)
ArrayView< const double > get_properties() const
bool operator==(const ParticleAccessor< dim, spacedim > &other) const
void set_id(const types::particle_index &new_id)
ArrayView< double, ::MemorySpace::Host > get_properties(const Handle handle)
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
Definition mpi.cc:734
std::size_t size
Definition mpi.cc:733
@ past_the_end
Iterator reached end of container.
@ valid
Iterator points to a valid object.
@ invalid
Iterator is invalid, probably due to an error.
Triangulation< dim, spacedim >::active_cell_iterator cell
ParticlesInCell(const std::vector< typename PropertyPool< dim, spacedim >::Handle > &particles, const typename Triangulation< dim, spacedim >::active_cell_iterator &cell)
std::vector< typename PropertyPool< dim, spacedim >::Handle > particles
result_type operator()(const ::Particles::ParticleAccessor< dim, spacedim > &accessor) const