sfc_partitioner.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser 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 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local Includes
21 #include "libmesh/libmesh_config.h"
22 #include "libmesh/mesh_base.h"
25 #include "libmesh/elem.h"
26 
27 #ifdef LIBMESH_HAVE_SFCURVES
28 namespace Sfc {
29 extern "C" {
30 # include "sfcurves.h"
31 }
32 }
33 #else
35 #endif
36 
37 namespace libMesh
38 {
39 
40 
44  unsigned int n)
45 {
46  // Check for easy returns
47  if (beg == end)
48  return;
49 
50  if (n == 1)
51  {
52  this->single_partition_range (beg, end);
53  return;
54  }
55 
56  libmesh_assert_greater (n, 0);
57 
58  // What to do if the sfcurves library IS NOT present
59 #ifndef LIBMESH_HAVE_SFCURVES
60 
61  libmesh_do_once(
62  libMesh::out << "ERROR: The library has been built without" << std::endl
63  << "Space Filling Curve support. Using a linear" << std::endl
64  << "partitioner instead!" << std::endl;);
65 
67  lp.partition_range (mesh, beg, end, n);
68 
69  // What to do if the sfcurves library IS present
70 #else
71 
72  LOG_SCOPE("partition_range()", "SFCPartitioner");
73 
74  // We don't yet support distributed meshes with this Partitioner
75  if (!mesh.is_serial())
76  libmesh_not_implemented();
77 
78  const dof_id_type n_range_elem = std::distance(beg, end);
79  const dof_id_type n_elem = mesh.n_elem();
80 
81  // The forward_map maps the range's element ids into a contiguous
82  // block of indices.
83  std::vector<dof_id_type> forward_map (n_elem, DofObject::invalid_id);
84 
85  // the reverse_map maps the contiguous ids back
86  // to active elements
87  std::vector<Elem *> reverse_map (n_range_elem, nullptr);
88 
89  std::vector<double> x (n_range_elem);
90  std::vector<double> y (n_range_elem);
91  std::vector<double> z (n_range_elem);
92  std::vector<int> table (n_range_elem);
93 
94  // Map the range's element ids into a contiguous range.
95  dof_id_type el_num = 0;
96 
97  for (auto & elem : as_range(beg, end))
98  {
99  libmesh_assert_less (elem->id(), forward_map.size());
100  libmesh_assert_less (el_num, reverse_map.size());
101 
102  forward_map[elem->id()] = el_num;
103  reverse_map[el_num] = elem;
104  el_num++;
105  }
106  libmesh_assert_equal_to (el_num, n_range_elem);
107 
108  // Get the centroid for each range element.
109  for (const auto & elem : as_range(beg, end))
110  {
111  libmesh_assert_less (elem->id(), forward_map.size());
112 
113  const Point p = elem->centroid();
114 
115  x[forward_map[elem->id()]] = p(0);
116  y[forward_map[elem->id()]] = p(1);
117  z[forward_map[elem->id()]] = p(2);
118  }
119 
120  // We need an integer reference to pass to the Sfc interface.
121  int size = static_cast<int>(n_range_elem);
122 
123  // build the space-filling curve
124  if (_sfc_type == "Hilbert")
125  Sfc::hilbert (x.data(),
126  y.data(),
127  z.data(),
128  &size,
129  table.data());
130 
131  else if (_sfc_type == "Morton")
132  Sfc::morton (x.data(),
133  y.data(),
134  z.data(),
135  &size,
136  table.data());
137 
138  else
139  {
140  libMesh::out << "ERROR: Unknown type: " << _sfc_type << std::endl
141  << " Valid types are" << std::endl
142  << " \"Hilbert\"" << std::endl
143  << " \"Morton\"" << std::endl
144  << " " << std::endl
145  << "Partitioning with a Hilbert curve." << std::endl;
146 
147  Sfc::hilbert (x.data(),
148  y.data(),
149  z.data(),
150  &size,
151  table.data());
152  }
153 
154 
155  // Assign the partitioning to the range elements
156  {
157  // {
158  // std::ofstream out ("sfc.dat");
159  // out << "variables=x,y,z" << std::endl;
160  // out << "zone f=point" << std::endl;
161  // for (unsigned int i=0; i<n_range_elem; i++)
162  // out << x[i] << " " << y[i] << " " << z[i] << std::endl;
163  // }
164 
165  const dof_id_type blksize = (n_range_elem + n - 1) / n;
166 
167  for (dof_id_type i=0; i<n_range_elem; i++)
168  {
169  libmesh_assert_less (static_cast<unsigned int>(table[i] - 1), reverse_map.size());
170 
171  Elem * elem = reverse_map[table[i] - 1];
172 
173  elem->processor_id() = cast_int<processor_id_type>(i/blksize);
174  }
175  }
176 
177 #endif
178 }
179 
180 
181 
183  const unsigned int n)
184 {
185  this->partition_range(mesh,
186  mesh.active_elements_begin(),
187  mesh.active_elements_end(),
188  n);
189 }
190 
191 } // namespace libMesh
virtual void partition_range(MeshBase &mesh, MeshBase::element_iterator it, MeshBase::element_iterator end, const unsigned int n) override
virtual void _do_partition(MeshBase &mesh, const unsigned int n) override
dof_id_type n_elem(const MeshBase::const_element_iterator &begin, const MeshBase::const_element_iterator &end)
Definition: mesh_tools.C:702
Partitions the elements based solely on their ids.
The base class for all geometric element types.
Definition: elem.h:100
MeshBase & mesh
IterBase * end
Base class for Mesh.
Definition: mesh_base.h:77
void single_partition_range(MeshBase::element_iterator it, MeshBase::element_iterator end)
Definition: partitioner.C:172
SimpleRange< I > as_range(const std::pair< I, I > &p)
Definition: simple_range.h:57
static const dof_id_type invalid_id
Definition: dof_object.h:347
virtual void partition_range(MeshBase &mesh, MeshBase::element_iterator it, MeshBase::element_iterator end, const unsigned int n) override
OStreamProxy out(std::cout)
processor_id_type processor_id() const
Definition: dof_object.h:717
A geometric point in (x,y,z) space.
Definition: point.h:38
uint8_t dof_id_type
Definition: id_types.h:64