Parallel Finite Element - General geometry Ewald-like Method
Part of Continuum-particle Simulation Suite under MICCOM
particle_mesh.h
Go to the documentation of this file.
1 // Parallel Finite Element-General Geometry Ewald-like Method.
2 // Copyright (C) 2015-2016 Xujun Zhao, Jiyuan Li, Xikai Jiang
3 
4 // This code is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 
10 // This code is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 
15 
16 // You should have received a copy of the GNU General Public
17 // License along with this code; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20 
21 
22 #pragma once
23 
24 // libmesh Includes -----------------------------------
25 #include "libmesh/libmesh_common.h"
26 #include "libmesh/reference_counted_object.h"
27 #include "libmesh/parallel_object.h"
28 #include "libmesh/mesh.h"
29 #include "libmesh/elem.h"
30 #include "libmesh/exodusII_io.h"
31 #ifdef LIBMESH_HAVE_NANOFLANN
32 # include "libmesh/nanoflann.hpp"
33 #endif
34 
35 
36 // Local Includes -----------------------------------
37 #include "rigid_particle.h"
38 #include "pm_periodic_boundary.h"
39 //#include "point_mesh.h"
40 
41 // C++ Includes -------------------------------------
42 //#include <stdio.h>
43 #include <string>
44 #include <vector>
45 
46 
47 namespace libMesh
48 {
49 
50 
51 //enum ParticleType {POINT, RIGID, DEFORMABLE};
52 
53 
54 //class RigidParticle;
55 
56 template <unsigned int KDDim>
57 class PointMesh;
58 
59 
60 
61 /*
62  * This template class defines particle-particle and particle-mesh
63  * mapping relations. It takes advantage of KD Tree library nanoflann
64  * to build the neighbor list for each particle.
65  *
66  * Generally speaking,for general shaped particles, their interaction
67  * is achieved by computing force values on each tracking point(mesh node).
68  * Therefore, the neighbor list may not be used in this case. However, we
69  * still provide this functionality for use in some special cases, for
70  * example, rigid particles with electrostatic interaction (no polarization)
71  */
72 
73 
74 
75 template <unsigned int KDDim>
76 class ParticleMesh : public ReferenceCountedObject<ParticleMesh<KDDim> >,
77  public ParallelObject
78 {
79 protected:
80 
81 #ifdef LIBMESH_HAVE_NANOFLANN
82 
90  template <unsigned int PLDim>
91  class PointListAdaptor
92  {
93  private:
94  /* use ref, which will point to the address of _particles in the parent class
95  * when _particles is modified, this ref need not to be updated
96  * when the values change
97  */
98  const std::vector<RigidParticle*> &_pts;
99 
100 
101  public:
102  // Constructor of PointListAdaptor
103  PointListAdaptor (const std::vector<RigidParticle*> &particles)
104  : _pts(particles)
105  { }
106 
110  typedef Real coord_t;
111  typedef std::size_t size_t;
112 
116  inline size_t kdtree_get_point_count() const { return _pts.size(); }
117 
122  inline coord_t kdtree_distance(const coord_t *p1, const size_t idx_p2, size_t size) const
123  {
124  libmesh_assert_equal_to (size, PLDim);
125  libmesh_assert_less (idx_p2, _pts.size());
126 
127  // retrieve the point data with index = idx_p2
128  const Point &p2( _pts[idx_p2]->get_centroid() );
129 
130  switch (size)
131  {
132  case 3:
133  {
134  const coord_t d0=p1[0] - p2(0);
135  const coord_t d1=p1[1] - p2(1);
136  const coord_t d2=p1[2] - p2(2);
137  return d0*d0 + d1*d1 + d2*d2;
138  }
139 
140  case 2:
141  {
142  const coord_t d0=p1[0] - p2(0);
143  const coord_t d1=p1[1] - p2(1);
144  return d0*d0 + d1*d1;
145  }
146 
147  case 1:
148  {
149  const coord_t d0=p1[0] - p2(0);
150  return d0*d0;
151  }
152  default:
153  libmesh_error_msg("ERROR: unknown size " << size);
154  }
155 
156  return -1.0;
157  } // end of kdtree_distance()
158 
164  inline coord_t kdtree_get_pt(const size_t idx, int dim) const
165  {
166  libmesh_assert_less (dim, (int) PLDim);
167  libmesh_assert_less (idx, _pts.size());
168  libmesh_assert_less (dim, 3);
169 
170  const Point &p(_pts[idx]->get_centroid() );
171  if (dim==0) return p(0);
172  if (dim==1) return p(1);
173  return p(2);
174  } // end of kdtree_get_pt()
175 
182  template <class BBOX>
183  bool kdtree_get_bbox(BBOX & /* bb */) const { return false; }
184 
185  }; // end of class PointListAdaptor
186 
187 
188  typedef nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<Real,PointListAdaptor<KDDim> >,
189  PointListAdaptor<KDDim>,
190  KDDim> kd_tree_t;
191  /*
192  * If a data member is declared mutable, then it is legal to assign a value
193  to this data member from a const member function.
194  */
195  mutable UniquePtr<kd_tree_t> _kd_tree;
196 
197 #endif // LIBMESH_HAVE_NANOFLANN
198 
199 
203  virtual void construct_kd_tree ();
204 
205 
206 
207 
208 public:
209  // Constructor
210  // Note if this is used to construct the object,
211  // users are responsible to set the search radius
212  // using the member function set_search_radius().
213  ParticleMesh(MeshBase& mesh);
214 
215 
216  // Constructor
217  ParticleMesh(MeshBase& mesh,
218  const Real& search_radius_p,
219  const Real& search_radius_e);
220 
221 
222  // Constructor
223  ParticleMesh(MeshBase& mesh,
224  PMPeriodicBoundary& pmpb,
225  const Real& search_radius_p,
226  const Real& search_radius_e);
227 
228  // Destructor
229  ~ParticleMesh();
230 
236  void read_particles_data(const std::string& filename, // particle xyz file
237  const std::string& particle_mesh_type); // mesh type of the particle);
238 
243  void read_particles_data_restart(const std::string& filename,
244  const std::string& particle_mesh_type);
248  void read_particles_data_restart(const std::string& filename,
249  const unsigned int& o_step);
250 
255  // void read_chromatin_data(const std::string& filename, // particle xyz file
256  // const std::string& vmesh_file, // volume mesh file name
257  // const std::string& smesh_file, // surface mesh file name
258  // const std::string& mesh_type); // mesh type of the particle
259 
260 
265  void generate_random_particles(const std::size_t N,
266  const Real bbox_XA, const Real bbox_XB,
267  const Real bbox_YA, const Real bbox_YB,
268  const Real bbox_ZA, const Real bbox_ZB);
269 
270 
271  void generate_random_particles(const std::size_t N,
272  const Point& bbox_min,
273  const Point& bbox_max);
274 
275 
276 
280  std::vector<RigidParticle*> particles() const { return _particles; }
281 
282 
286  std::size_t num_particles() const { return _n_rigid_particles; }
287 
288 
292  bool is_sorted() const { return _is_sorted; }
293 
294 
295 
307  void reinit();
308 
309 
313  void print_particle_info() const;
314 
315 
319  void set_search_radius(const Real rp, const Real re)
320  { _search_radius_p = rp; _search_radius_e = re; };
321 
322 
326  Real search_radius(const std::string & p_e) const;
327 
328 
333  { _periodic_boundary = &_periodic_bdry; }
334 
335 
340  { return _periodic_boundary; }
341 
342 
343  /*
344  * Return the Mesh
345  */
346  MeshBase& mesh(){ return _mesh; }
347 
348 
349  /*
350  * Total number of the tracking points on the mesh,
351  * which is the sum of number of nodes on each particle's mesh
352  */
353  std::size_t num_mesh_points() const;
354 
355 
356  /*
357  * Update the mesh for each particle
358  * This is achieved by updating each nodal coordinates.
359  */
360  void update_mesh(const std::vector<Point>& nodal_pos,
361  const std::vector<Point>& nodal_vel);
362  // void update_mesh(const std::vector<Real> & nodal_vec);
363 
364 
365  // /*
366  // * update the (input) point_mesh object according to the particle_mesh
367  // * particle_mesh doesn't change, but point_mesh is changed.
368  // *
369  // * This function updates the input class, but doesn't change its own data.
370  // */
371  // void update_point_mesh(PointMesh<KDDim>* point_mesh) const;
372 
373 
374  // /*
375  // * update the particle_mesh object according to the (input) point_mesh
376  // * The input point_mesh doesn't change, but particle_mesh is changed.
377  // */
378  // void update_particle_mesh(const PointMesh<KDDim>* point_mesh);
379 
380 
381  /*
382  * zero particle force density
383  */
384  void zero_node_force();
385 
386 
387  /*
388  * Return the mesh size (hmin/hmax) associated with this particle
389  */
390  std::vector<Real> mesh_size() const;
391 
392 
393  /*
394  * Correct the position of tracking points to avoid volume change!
395  * NOTE: this is only for surface mesh.
396  */
397  void volume_conservation();
398 
399 
400  /*
401  * compute center of mass at step 0: center0, for rigid particles
402  */
403  void initial_particle_center_of_mass(std::vector<Point>& center0) const;
404 
405  /*
406  * Write particle
407  */
408  void write_particle(const unsigned int& step_id,
409  const unsigned int& o_step,
410  const Real& real_time,
411  const std::vector<std::string>& output_file,
412  unsigned int comm_in_rank) const;
413 
414  /*
415  * write out step and real time
416  */
417  void write_time(const unsigned int& step_id,
418  const unsigned int& o_step,
419  const Real& real_time,
420  unsigned int comm_in_rank) const;
421 
422 
423  /*
424  * Write out particle trajectories && forces && velocity to csv files
425  * "output_bead_o_step.csv"
426  */
427  void write_particle_trajectory(const unsigned int& o_step,
428  unsigned int comm_in_rank) const;
429 
430  /*
431  * Write out surface nodes positions to csv files
432  */
433  void write_surface_node(const unsigned int& o_step,
434  unsigned int comm_in_rank) const;
435 
436 
437  /*
438  * Write out the particle's mesh(either surface mesh or volume mesh)
439  */
440  void write_particle_mesh(const unsigned int& o_step) const;
441 
442  /*
443  * Write out restart mesh (only save the latest step)
444  */
445  void write_particle_mesh_restart() const;
446 
447  /*
448  * Return a stitched mesh associated with all particles for electrostatic solver
449  * and assign particle's id to subdomain_id
450  */
451  SerialMesh& stitched_mesh();
452 
453 
454 /********************************************************************************
455  Uncomment play around the section below to construct neighbor_list for
456  rigidParticle-rigidParticle and rigidParticle-elem
457 ********************************************************************************/
458 
464  std::map<const std::size_t, std::vector<std::size_t> > elem_neighbor_list() const
465  { return _elem_neighbor_list; }
466 
467 
472  const std::vector<std::size_t> elem_neighbor_list(const Elem* elem)
473  {
474  const std::size_t elem_id = elem->id();
475  return _elem_neighbor_list[elem_id];
476  //return _elem_neighbor_list.at(elem_id); // not work well
477  }
478 
479 
484  const std::vector<std::size_t> local_elem_neighbor_list(const Elem* elem)
485  {
486  const std::size_t elem_id = elem->id();
487  return _local_elem_neighbor_list[elem_id];
488  }
489 
490 
495  virtual void clear_kd_tree();
496 
497 
498 
507  virtual void build_particle_neighbor_list(const Point &query_pt,
508  const bool is_sorted,
509  std::vector<std::pair<std::size_t,Real> >& IndicesDists);
510 
511 
517  virtual void build_particle_neighbor_list();
518 
519 
520 
527 
528 
538  virtual void build_elem_neighbor_list(const Elem* elem,
539  const bool is_sorted,
540  std::vector<std::size_t>& n_list);
541 
542 
549  virtual void build_elem_neighbor_list();
550 
554  void print_elem_neighbor_list(std::ostream & out = libMesh::out) const;
555 
556 private:
557  // number of rigid particles
558  std::size_t _n_rigid_particles;
559 
560  // number of rigid particle types
561  std::size_t _n_rigid_particle_types;
562 
563  // number of rigid particle mesh types
564  std::size_t _n_rigid_particle_mesh_types;
565 
566  // mass values of rigid particles
567  std::vector<Real> _mass;
568 
569  // mesh files
570  std::vector<std::string> _rigid_particle_mesh_files;
571 
572  // A vector that store the pointers to Particle
573  std::vector<RigidParticle*> _particles;
574 
575  // Mesh base: this is the domain(fluid) mesh, not the particle's mesh
576  MeshBase& _mesh;
577 
578  // dimension
579  std::size_t _dim;
580 
581  // Search radius (around a particle)
582  Real _search_radius_p;
583 
584  // Search radius (around an element)
585  Real _search_radius_e;
586 
587  // The point list adapter
588  // - interface to the nanoflann in order to construct KD-Tree
589  PointListAdaptor<KDDim> _point_list_adaptor;
590 
591  // Is the neighbor list sorted? set true defaultly (particle/elem neighbor list)
592  bool _is_sorted;
593 
594 
595  // Element neighbor list: mapping between Elem and particle id's around it
596  // This is NOT necessary to be on all the processors in implementation,
597  // but we do this here only for test purpose. For local build
598  std::map<const std::size_t, std::vector<std::size_t> > _elem_neighbor_list;
599  std::map<const std::size_t, std::vector<std::size_t> > _local_elem_neighbor_list;
600 
601  // Pointer to the Periodic boundary condition
602  PMPeriodicBoundary* _periodic_boundary;
603 
604  // precision of output
605  const int o_precision = 6;
606 };
607 
608 
609 }
void write_particle_trajectory(const unsigned int &o_step, unsigned int comm_in_rank) const
Definition: particle_mesh.C:752
Definition: particle_mesh.h:76
void write_surface_node(const unsigned int &o_step, unsigned int comm_in_rank) const
Definition: particle_mesh.C:794
virtual void build_particle_neighbor_list_naively()
Definition: particle_mesh.C:1071
virtual void clear_kd_tree()
Definition: particle_mesh.C:940
virtual void build_elem_neighbor_list()
Definition: particle_mesh.C:1198
ParticleMesh(MeshBase &mesh)
Definition: particle_mesh.C:48
void set_search_radius(const Real rp, const Real re)
Definition: particle_mesh.h:319
PMPeriodicBoundary * pm_periodic_boundary()
Definition: particle_mesh.h:339
void reinit()
Definition: particle_mesh.C:441
Real search_radius(const std::string &p_e) const
Definition: particle_mesh.C:504
void add_periodic_boundary(PMPeriodicBoundary &_periodic_bdry)
Definition: particle_mesh.h:332
Definition: brownian_system.h:58
void generate_random_particles(const std::size_t N, const Real bbox_XA, const Real bbox_XB, const Real bbox_YA, const Real bbox_YB, const Real bbox_ZA, const Real bbox_ZB)
Definition: particle_mesh.C:376
Definition: pm_periodic_boundary.h:46
MeshBase & mesh()
Definition: particle_mesh.h:346
SerialMesh & stitched_mesh()
Definition: particle_mesh.C:864
void write_particle(const unsigned int &step_id, const unsigned int &o_step, const Real &real_time, const std::vector< std::string > &output_file, unsigned int comm_in_rank) const
Definition: particle_mesh.C:696
const std::vector< std::size_t > elem_neighbor_list(const Elem *elem)
Definition: particle_mesh.h:472
void write_particle_mesh_restart() const
Definition: particle_mesh.C:849
virtual void construct_kd_tree()
Definition: particle_mesh.C:916
std::map< const std::size_t, std::vector< std::size_t > > elem_neighbor_list() const
Definition: particle_mesh.h:464
void write_time(const unsigned int &step_id, const unsigned int &o_step, const Real &real_time, unsigned int comm_in_rank) const
Definition: particle_mesh.C:729
std::vector< Real > mesh_size() const
Definition: particle_mesh.C:641
std::vector< RigidParticle * > particles() const
Definition: particle_mesh.h:280
void write_particle_mesh(const unsigned int &o_step) const
Definition: particle_mesh.C:830
void print_elem_neighbor_list(std::ostream &out=libMesh::out) const
Definition: particle_mesh.C:1398
void initial_particle_center_of_mass(std::vector< Point > &center0) const
Definition: particle_mesh.C:684
virtual void build_particle_neighbor_list()
Definition: particle_mesh.C:1042
void read_particles_data(const std::string &filename, const std::string &particle_mesh_type)
Definition: particle_mesh.C:112
std::size_t num_particles() const
Definition: particle_mesh.h:286
void print_particle_info() const
Definition: particle_mesh.C:537
void zero_node_force()
Definition: particle_mesh.C:629
const std::vector< std::size_t > local_elem_neighbor_list(const Elem *elem)
Definition: particle_mesh.h:484
void update_mesh(const std::vector< Point > &nodal_pos, const std::vector< Point > &nodal_vel)
Definition: particle_mesh.C:553
void read_particles_data_restart(const std::string &filename, const std::string &particle_mesh_type)
Definition: particle_mesh.C:270
void volume_conservation()
Definition: particle_mesh.C:668
~ParticleMesh()
Definition: particle_mesh.C:99
bool is_sorted() const
Definition: particle_mesh.h:292
std::size_t num_mesh_points() const
Definition: particle_mesh.C:519
Definition: particle_mesh.h:57