From ee615f3cb71767679a2fefa065af6f81bfc14ca3 Mon Sep 17 00:00:00 2001
From: Bruno <blais.bruno@gmail.com>
Date: Tue, 17 Nov 2020 21:07:02 -0500
Subject: [PATCH] Add particle update data function to overwrite particle
 information without recreating the particle Added documentation and fixed
 indentation Added out to documentation

Co-authored-by: Martin Kronbichler <kronbichler@lnm.mw.tum.de>
---
 include/deal.II/particles/particle.h | 19 +++++++++++++++++++
 source/particles/particle.cc         | 28 ++++++++++++++++++++++++++++
 source/particles/particle_handler.cc |  6 +++---
 3 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/include/deal.II/particles/particle.h b/include/deal.II/particles/particle.h
index a79617d223..e43dc03b31 100644
--- a/include/deal.II/particles/particle.h
+++ b/include/deal.II/particles/particle.h
@@ -235,6 +235,25 @@ namespace Particles
     void
     write_data(void *&data) const;
 
+
+    /**
+     * Update all of the data associated with a particle : id,
+     * location, reference location and, if any, properties by using a
+     * data array. The array is expected to be large enough to take the data,
+     * and the void pointer should point to the first entry of the array to
+     * which the data should be written. This function is meant for
+     * de-serializing the particle data without requiring that a new Particle
+     * class be built. This is used in the ParticleHandler to update the
+     * ghost particles without de-allocating and re-allocating memory.
+     *
+     * @param[in,out] data A pointer to a memory location from which
+     * to read the information that completely describes a particle. This
+     * class then de-serializes its data from this memory location and
+     * advance the pointer accordingly.
+     */
+    void
+    update_particle_data(const void *&data);
+
     /**
      * Set the location of this particle. Note that this does not check
      * whether this is a valid location in the simulation domain.
diff --git a/source/particles/particle.cc b/source/particles/particle.cc
index 2befeec29c..0a68480dc1 100644
--- a/source/particles/particle.cc
+++ b/source/particles/particle.cc
@@ -220,6 +220,34 @@ namespace Particles
   }
 
 
+  template <int dim, int spacedim>
+  void
+  Particle<dim, spacedim>::update_particle_data(const void *&data)
+  {
+    const types::particle_index *id_data =
+      static_cast<const types::particle_index *>(data);
+    id                  = *id_data++;
+    const double *pdata = reinterpret_cast<const double *>(id_data);
+
+    for (unsigned int i = 0; i < spacedim; ++i)
+      location(i) = *pdata++;
+
+    for (unsigned int i = 0; i < dim; ++i)
+      reference_location(i) = *pdata++;
+
+    // See if there are properties to load
+    if (has_properties())
+      {
+        const ArrayView<double> particle_properties =
+          property_pool->get_properties(properties);
+        const unsigned int size = particle_properties.size();
+        for (unsigned int i = 0; i < size; ++i)
+          particle_properties[i] = *pdata++;
+      }
+
+    data = static_cast<const void *>(pdata);
+  }
+
 
   template <int dim, int spacedim>
   std::size_t
diff --git a/source/particles/particle_handler.cc b/source/particles/particle_handler.cc
index 783bd95091..fd3fc03874 100644
--- a/source/particles/particle_handler.cc
+++ b/source/particles/particle_handler.cc
@@ -1649,9 +1649,9 @@ namespace Particles
 
     for (auto &recv_particle : ghost_particles_iterators)
       {
-        recv_particle->second.free_properties();
-        recv_particle->second =
-          Particle<dim, spacedim>(recv_data_it, property_pool.get());
+        // Update particle data using previously allocated memory space
+        // for efficiency reasons
+        recv_particle->second.update_particle_data(recv_data_it);
 
         if (load_callback)
           recv_data_it =
-- 
2.39.5