direct_product_mesh.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra Wonton project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/wonton/blob/master/LICENSE
5 */
6 
7 #ifndef WONTON_DIRECT_PRODUCT_MESH_H_
8 #define WONTON_DIRECT_PRODUCT_MESH_H_
9 
10 #include <array>
11 #include <cassert>
12 #include <vector>
13 
14 #include "wonton/support/wonton.h"
17 
28 namespace Wonton {
29 
111 template<int D, class CoordSys=Wonton::DefaultCoordSys>
113 
114  public:
115 
116  // ==========================================================================
117  // Constructors and destructors
118 
120  Direct_Product_Mesh() = delete;
121 
132  Direct_Product_Mesh(const std::array<std::vector<double>,D> &axis_points_in,
133  const Wonton::Executor_type *executor = nullptr,
134  const int num_ghost_layers = 0,
135  const int dpart = D);
136 
139  const Direct_Product_Mesh<D,CoordSys> &) = delete;
140 
141  // ==========================================================================
142  // Accessors
143 
147  int space_dimension() const;
148 
152  bool distributed() const;
153 
161  int num_axis_points(const int dim,
162  const Entity_type etype = Entity_type::ALL) const;
163 
171  int num_ghost_layers() const;
172 
179  Entity_type axis_point_type(const int dim, const int pointid) const;
180 
188  GID_t point_global_index(const int dim, const int pointid) const;
189 
196  int num_axis_cells(const int dim,
197  const Entity_type etype = Entity_type::ALL) const;
198 
211  double get_axis_point(const int dim, const int pointid) const;
212 
219  bool point_on_external_boundary(const int dim, const int pointid) const;
220 
227  void get_global_coord_bounds(const int dim, double *lo, double *hi) const;
228 
235  void get_local_coord_bounds(const int dim, double *lo, double *hi) const;
236 
237  private:
238 
239  // ==========================================================================
240  // Class data
241 
243  std::array<std::array<double,2>,D> coord_bounds_global_;
244 
246  std::array<GID_t,D> num_axis_points_global_;
247 
249  int num_ghost_layers_;
250 
253  std::array<std::array<GID_t,2>,D> gid_bounds_local_;
254 
256  std::array<std::vector<double>,D> axis_points_;
257 
259  bool distributed_=false;
260 
261 #ifdef WONTON_ENABLE_MPI
262  MPI_Comm mycomm_;
263  int nprocs_=1;
264  int rank_=0;
265 #endif
266 
267 }; // class Direct_Product_Mesh
268 
269 
270 // ============================================================================
271 // Constructors and destructors
272 
273 // ____________________________________________________________________________
274 // Constructor
275 
276 template<int D, class CoordSys>
278  const std::array<std::vector<double>,D> &axis_points_in,
279  Wonton::Executor_type const *executor, int num_ghost_layers, int dpart) {
280 
281  for (int d = 0; d < D; d++) {
282  coord_bounds_global_[d][0] = axis_points_in[d][0];
283  coord_bounds_global_[d][1] = axis_points_in[d][axis_points_in[d].size()-1];
284  num_axis_points_global_[d] = axis_points_in[d].size();
285  }
286 
287 #ifdef WONTON_ENABLE_MPI
288 
289  mycomm_ = MPI_COMM_NULL;
290  auto mpiexec = dynamic_cast<MPIExecutor_type const *>(executor);
291  if (mpiexec && mpiexec->mpicomm != MPI_COMM_NULL) {
292  mycomm_ = mpiexec->mpicomm;
293  MPI_Comm_size(mycomm_, &nprocs_);
294  MPI_Comm_rank(mycomm_, &rank_);
295  if (nprocs_ > 1) distributed_ = true;
296  }
297  if (distributed_) {
298  // compute partition of the global domain on each processor
299 
300  int seed = 42; // seed for randomization to ensure we get
301  // consistent results on all processors
302 
303  std::array<GID_t, D> ncells;
304  for (int d = 0; d < D; d++) ncells[d] = axis_points_in[d].size()-1;
305  auto partition_bounds =
306  structured_partitioner<D>(nprocs_, ncells, dpart, seed);
307 
308  // integer bounds of points of OWNED cells in each direction on
309  // local partition. The 'partition_bounds' are returned as
310  // ((xlo,ylo,zlo),(xhi,yhi,zhi)) while bounds in this class are
311  // stored as ((xlo,xhi),(ylo,yhi),(zlo,zhi))
312 
313  for (int d = 0; d < D; d++) {
314  gid_bounds_local_[d][0] = partition_bounds[rank_][0][d];
315  gid_bounds_local_[d][1] = partition_bounds[rank_][1][d];
316  }
317 
318  // Build list of axis points including ghost points
319 
320  num_ghost_layers_ = num_ghost_layers;
321  int NG = num_ghost_layers_;
322 
323  double inf = std::numeric_limits<double>::infinity();
324  for (int d = 0; d < D; d++) {
325  GID_t lo = gid_bounds_local_[d][0];
326  GID_t hi = gid_bounds_local_[d][1];
327 
328  // owned + ghost points
329  int npall = static_cast<int>(hi-lo+1+2*NG);
330  axis_points_[d].resize(npall);
331 
332  if (lo == 0)
333  for (int k = 0; k < NG; k++)
334  axis_points_[d][k] = -inf;
335  else
336  for (int k = 0; k < NG; k++)
337  axis_points_[d][k] = (lo-NG+k < 0) ? -inf :
338  axis_points_[d][k] = axis_points_in[d][lo-NG+k];
339 
340  std::copy(axis_points_in[d].begin()+lo, axis_points_in[d].begin()+hi+1,
341  axis_points_[d].begin()+NG);
342 
343  if (hi == num_axis_points_global_[d]-1)
344  for (int k = 0; k < NG; k++)
345  axis_points_[d][npall-NG+k] = inf;
346  else
347  for (int k = 0; k < NG; k++)
348  axis_points_[d][npall-NG+k] = (hi+1+k >= num_axis_points_global_[d]) ?
349  inf : axis_points_in[d][hi+1+k];
350  }
351  } else {
352  num_ghost_layers_ = 0;
353  for (int d = 0; d < D; ++d)
354  axis_points_[d] = axis_points_in[d];
355  for (int d = 0; d < D; ++d) {
356  gid_bounds_local_[d][0] = 0;
357  gid_bounds_local_[d][1] = num_axis_points_global_[d];
358  }
359  }
360 
361 #else
362  num_ghost_layers_ = 0;
363  for (int d = 0; d < D; ++d)
364  axis_points_[d] = axis_points_in[d];
365  for (int d = 0; d < D; ++d) {
366  gid_bounds_local_[d][0] = 0;
367  gid_bounds_local_[d][1] = num_axis_points_global_[d];
368  }
369 #endif
370 
371 }
372 
373 
374 // ============================================================================
375 // Accessors
376 
377 // ____________________________________________________________________________
378 // Get the dimensionality of the mesh.
379 template<int D, class CoordSys>
381  return(D);
382 }
383 
384 // ____________________________________________________________________________
385 // Is the mesh distributed?
386 template<int D, class CoordSys>
388  return(distributed_);
389 }
390 
391 // ____________________________________________________________________________
392 // Get the number of axis points (cell boundary coordinates) of particular type
393 template<int D, class CoordSys>
395  Entity_type etype) const {
396  assert(dim >= 0);
397  assert(dim < D);
398  switch(etype) {
399  case PARALLEL_OWNED: {
400  // Eliminate the guaranteed ghost points (i.e. lower points of
401  // ghost cells before the owned cells and the upper points of
402  // ghost cells after the owned cells). For instance, if there
403  // are 2 ghost layers, then 4 points are guaranteed to be
404  // ghosts as shown here (g is ghost, o is owned):
405  //
406  // axis pts g g g/o o o o g g
407  // *-----*-----*-----*-----*-----*-----*-----*
408  // cells g g o o o o o
409 
410  int n = axis_points_[dim].size()-2*num_ghost_layers_;
411 
412  // the upper coordinate of the partition in any direction is
413  // ALWAYS owned by the current partition while the lower
414  // coordinate of the partition in any direction is ghost (owned
415  // by another partition) _unless_ it is on the outer low
416  // boundary of global domain
417 
418  if (gid_bounds_local_[dim][0] != 0)
419  n--;
420  return n;
421  }
422  case PARALLEL_GHOST: {
423  int n = 2*num_ghost_layers_;
424  if (gid_bounds_local_[dim][0] != 0) // see figure above
425  n++;
426  return n;
427  }
428  case ALL:
429  return axis_points_[dim].size();
430  default:
431  return 0;
432  }
433 }
434 
435 
436 // ____________________________________________________________________________
437 // Get the number of ghost layers on this mesh
438 template<int D, class CoordSys>
440  return num_ghost_layers_;
441 }
442 
443 // ____________________________________________________________________________
444 // Get the specified axis point (cell boundary coordinate).
445 template<int D, class CoordSys>
447  const int dim, const int pointid) const {
448  assert(dim >= 0);
449  assert(dim < D);
450 
451 #if DEBUG
452  int npall = axis_points_[dim].size();
453  assert(pointid >= -num_ghost_layers_);
454  assert(pointid <= npall);
455 #endif
456 
457  // pointid starts at -num_ghost_layers for lowest ghost point
458  return axis_points_[dim][pointid+num_ghost_layers_];
459 }
460 
461 // ____________________________________________________________________________
462 // is point on external (global) boundary along given axis
463 // Both the owned points on the global boundary AND their boundary
464 // ghost counterparts will return true in this call
465 template<int D, class CoordSys>
467  const int dim, const int pointid) const {
468  assert(dim >= 0);
469  assert(dim < D);
470 
471  GID_t global_point_index = point_global_index(dim, pointid);
472  if (global_point_index <= 0)
473  return true; // coord on or outside of lower global bounds
474  else return global_point_index >= num_axis_points_global_[dim] - 1;
475 }
476 
477 
478 // ____________________________________________________________________________
479 // Entity type of a point along the axis
480 template<int D, class CoordSys>
482  const int dim, const int pointid) const {
483  int npall = num_axis_points(dim, ALL);
484  if (point_on_external_boundary(dim, pointid)) { // global boundary
485  if (pointid < 0 || pointid > npall-2*num_ghost_layers_-1)
486  return BOUNDARY_GHOST;
487  else if (pointid == 0)
488  return PARALLEL_OWNED; // lo bndry of owned cells in partition
489  else if (pointid == npall-2*num_ghost_layers_-1)
490  return PARALLEL_GHOST; // hi bndry of owned cells in partition
491  } else {
492  if (pointid < 0 || pointid >= npall-2*num_ghost_layers_-1)
493  return PARALLEL_GHOST;
494  else
495  return PARALLEL_OWNED;
496  }
497  return TYPE_UNKNOWN;
498 }
499 
500 // ____________________________________________________________________________
501 // get global index of point along given axis
502 
503 // Note: we expect the number of points along any one axis to be well
504 // within the range representable by an int
505 template<int D, class CoordSys>
507  const int dim, const int pointid) const {
508  assert(dim >= 0);
509  assert(dim < D);
510 
511  return gid_bounds_local_[dim][0] + pointid;
512 }
513 
514 // ____________________________________________________________________________
515 // number of cells along given axis
516 template<int D, class CoordSys>
518  const int dim, const Entity_type etype) const {
519  assert(dim >= 0);
520  assert(dim < D);
521  switch (etype) {
522  case ALL:
523  return num_axis_points(dim, ALL) - 1;
524  case PARALLEL_OWNED:
525  return num_axis_points(dim, ALL) - 1 - 2*num_ghost_layers_;
526  case PARALLEL_GHOST:
527  return 2*num_ghost_layers_;
528  default:
529  return 0;
530  }
531 }
532 
533 
534 // ____________________________________________________________________________
535 // Coordinate bounds of global domain
536 template<int D, class CoordSys>
538  double *plo,
539  double *phi) const {
540  *plo = coord_bounds_global_[dim][0];
541  *phi = coord_bounds_global_[dim][1];
542 }
543 
544 // ____________________________________________________________________________
545 // Coordinate bounds of owned cells in local domain (ghost layers EXCLUDED)
546 template<int D, class CoordSys>
548  double *plo,
549  double *phi) const {
550  int npall = axis_points_[dim].size();
551  *plo = axis_points_[dim][num_ghost_layers_];
552  *phi = axis_points_[dim][npall-1-num_ghost_layers_];
553 }
554 
555 
556 } // namespace Wonton
557 
558 #endif // WONTON_DIRECT_PRODUCT_MESH_H_
int num_axis_cells(const int dim, const Entity_type etype=Entity_type::ALL) const
Get the number of cell along a specified axis.
Definition: direct_product_mesh.h:517
Definition: wonton.h:130
Definition: wonton.h:128
void get_local_coord_bounds(const int dim, double *lo, double *hi) const
coordinate bounds of OWNED cells in local domain (ghost layers EXCLUDED)
Definition: direct_product_mesh.h:547
int num_ghost_layers() const
Number of ghost layers on any end.
Definition: direct_product_mesh.h:439
Direct_Product_Mesh()=delete
Default constructor (disabled)
Definition: wonton.h:129
void get_global_coord_bounds(const int dim, double *lo, double *hi) const
get global coordinate bounds along axis
Definition: direct_product_mesh.h:537
Factorize a number N into D equal (or nearly equal) factors.
Definition: adaptive_refinement_mesh.h:31
Entity_type
The parallel type of a given entity.
Definition: wonton.h:124
Definition: wonton.h:125
Definition: wonton.h:225
bool distributed() const
Is the mesh distributed.
Definition: direct_product_mesh.h:387
bool point_on_external_boundary(const int dim, const int pointid) const
is point on external (global) boundary along given axis
Definition: direct_product_mesh.h:466
A basic, axis-aligned, logically-rectangular mesh.
Definition: direct_product_mesh.h:112
Entity_type axis_point_type(const int dim, const int pointid) const
Entity type of axis point.
Definition: direct_product_mesh.h:481
GID_t point_global_index(const int dim, const int pointid) const
Global index of point along a specified axis.
Definition: direct_product_mesh.h:506
double get_axis_point(const int dim, const int pointid) const
Get the specified axis point (coordinate value of cell corner)
Definition: direct_product_mesh.h:446
int64_t GID_t
Definition: wonton.h:76
int num_axis_points(const int dim, const Entity_type etype=Entity_type::ALL) const
Get the number of axis points (cell boundary coordinates) along a specified axis. ...
Definition: direct_product_mesh.h:394
Direct_Product_Mesh & operator=(const Direct_Product_Mesh< D, CoordSys > &)=delete
Assignment operator (disabled).
Definition: wonton.h:127
int space_dimension() const
Get the dimensionality of the mesh.
Definition: direct_product_mesh.h:380