zoltanRenumber.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Class
27  Foam::zoltanRenumber
28 
29 Description
30  Renumber using Zoltan
31 
32  Zoltan install:
33  - in your ~/.bashrc:
34  export ZOLTAN_ARCH_DIR=\
35  $WM_THIRD_PARTY_DIR/platforms/linux64Gcc/Zoltan_XXX
36  - unpack into $WM_THIRD_PARTY_DIR
37  - cd Zoltan_XXX
38  - mkdir build
39  - cd build
40  - export CCFLAGS="-fPIC"
41  - export CXXFLAGS="-fPIC"
42  - export CFLAGS="-fPIC"
43  - export LDFLAGS="-shared"
44  - ../configure \
45  --prefix=$ZOLTAN_ARCH_DIR \
46  --with-ccflags=-fPIC --with-cxxflags=-fPIC --with-ldflags=-shared
47 
48 SourceFiles
49  zoltanRenumber.C
50 
51 \*---------------------------------------------------------------------------*/
52 
53 #include "zoltanRenumber.H"
55 #include "IFstream.H"
56 #include "labelIOList.H"
57 #include "polyMesh.H"
58 #include "globalMeshData.H"
59 #include "globalIndex.H"
60 #include "uint.H"
61 
62 // Include MPI without any C++ bindings
63 #ifndef MPICH_SKIP_MPICXX
64 #define MPICH_SKIP_MPICXX
65 #endif
66 #ifndef OMPI_SKIP_MPICXX
67 #define OMPI_SKIP_MPICXX
68 #endif
69 
70 #pragma GCC diagnostic ignored "-Wold-style-cast"
71 #include "zoltan.h"
72 #include <mpi.h>
73 
74 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
75 
76 namespace Foam
77 {
78  defineTypeNameAndDebug(zoltanRenumber, 0);
79 
81  (
82  renumberMethod,
83  zoltanRenumber,
84  dictionary
85  );
86 }
87 
88 
89 static int get_number_of_vertices(void *data, int *ierr)
90 {
91  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
92  *ierr = ZOLTAN_OK;
93  return mesh.nCells();
94 }
95 
96 
97 static void get_vertex_list(void *data, int sizeGID, int sizeLID,
98  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
99  int wgt_dim, float *obj_wgts, int *ierr)
100 {
101  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
102 
103  *ierr = ZOLTAN_OK;
104 
105  /* In this example, return the IDs of our vertices, but no weights.
106  * Zoltan will assume equally weighted vertices.
107  */
108 
109  wgt_dim = 0;
110  obj_wgts = nullptr;
111 
112  for (Foam::label i=0; i<mesh.nCells(); i++)
113  {
114  globalID[i] = i; // should be global
115  localID[i] = i;
116  }
117 }
118 
119 
120 static void get_num_edges_list(void *data, int sizeGID, int sizeLID,
121  int num_obj,
122  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
123  int *numEdges, int *ierr)
124 {
125  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
126 
127  if ((sizeGID != 1) || (sizeLID != 1) || (num_obj != mesh.nCells()))
128  {
129  *ierr = ZOLTAN_FATAL;
130  return;
131  }
132 
133  for (Foam::label i=0; i < num_obj ;i++)
134  {
135  Foam::label celli = localID[i];
136  const Foam::cell& cFaces = mesh.cells()[celli];
137  forAll(cFaces, cFacei)
138  {
139  Foam::label n = 0;
140  if (mesh.isInternalFace(cFaces[cFacei]))
141  {
142  n++;
143  }
144  numEdges[i] = n;
145  }
146  }
148  *ierr = ZOLTAN_OK;
149 }
150 
151 
152 static void get_edge_list(void *data, int sizeGID, int sizeLID,
153  int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
154  int *num_edges,
155  ZOLTAN_ID_PTR nborGID, int *nborProc,
156  int wgt_dim, float *ewgts, int *ierr)
157 {
158  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
159 
160  if
161  (
162  (sizeGID != 1)
163  || (sizeLID != 1)
164  || (num_obj != mesh.nCells())
165  || (wgt_dim != 1)
166  )
167  {
168  *ierr = ZOLTAN_FATAL;
169  return;
170  }
171 
172  ZOLTAN_ID_TYPE* nextNbor = nborGID;
173  int* nextProc = nborProc;
174  float* nextWgt = ewgts;
175 
176  for (Foam::label i=0; i < num_obj; i++)
177  {
178  Foam::label celli = localID[i];
179 
180  const Foam::cell& cFaces = mesh.cells()[celli];
181  forAll(cFaces, cFacei)
182  {
183  Foam::label n = 0;
184 
185  Foam::label facei = cFaces[cFacei];
186  if (mesh.isInternalFace(facei))
187  {
188  Foam::label nbr = mesh.faceOwner()[facei];
189  if (nbr == celli)
190  {
191  nbr = mesh.faceNeighbour()[facei];
192  }
193 
194  // Note: global index
195  *nextNbor++ = nbr;
196  *nextProc++ = 0;
197  *nextWgt++ = 1.0;
198 
199  n++;
200  }
201  if (n != num_edges[i])
202  {
203  *ierr = ZOLTAN_FATAL;
204  return;
205  }
206  }
207  }
208  *ierr = ZOLTAN_OK;
209 }
210 
211 
212 static int get_mesh_dim(void *data, int *ierr)
213 {
214  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
215 
216  return mesh.nSolutionD();
217 }
218 
219 
220 static void get_geom_list
221 (
222  void *data,
223  int num_gid_entries,
224  int num_lid_entries,
225  int num_obj,
226  ZOLTAN_ID_PTR global_ids,
227  ZOLTAN_ID_PTR local_ids,
228  int num_dim,
229  double *geom_vec,
230  int *ierr
231 )
232 {
233  const Foam::polyMesh& mesh = *static_cast<const Foam::polyMesh*>(data);
234 
235  if
236  (
237  (num_gid_entries != 1)
238  || (num_lid_entries != 1)
239  || (num_obj != mesh.nCells())
240  || (num_dim != mesh.nSolutionD())
241  )
242  {
243  *ierr = ZOLTAN_FATAL;
244  return;
245  }
246 
247  double* p = geom_vec;
248 
249 
250  const Foam::Vector<Foam::label>& sol = mesh.solutionD();
251 
252  const Foam::pointField& cc = mesh.cellCentres();
253 
254  for (Foam::label celli = 0; celli < num_obj; celli++)
255  {
256  const Foam::point& pt = cc[celli];
257 
258  for (Foam::direction cmpt = 0; cmpt < Foam::vector::nComponents; cmpt++)
259  {
260  if (sol[cmpt] == 1)
261  {
262  *p++ = pt[cmpt];
263  }
264  }
265  }
266  *ierr = ZOLTAN_OK;
267 }
268 
269 
270 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
271 
272 Foam::zoltanRenumber::zoltanRenumber(const dictionary& dict)
273 :
275  coeffsDict_(dict.optionalSubDict(typeName+"Coeffs"))
276 {}
278 
279 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
280 
282 (
283  const polyMesh& pMesh,
284  const pointField& points
285 ) const
286 {
287  stringList args(1);
288  args[0] = "zoltanRenumber";
289 
290  int argc = args.size();
291  char* argv[argc];
292  for (label i = 0; i < argc; i++)
293  {
294  argv[i] = strdup(args[i].c_str());
295  }
296 
297  float ver;
298  int rc = Zoltan_Initialize(argc, argv, &ver);
299 
300  Foam::Pout<< "Initialised to " << ver << Foam::endl;
301 
302  if (rc != ZOLTAN_OK)
303  {
305  << "Failed initialising Zoltan" << exit(FatalError);
306  }
307 
308  struct Zoltan_Struct *zz = Zoltan_Create(MPI_COMM_WORLD);
309 
310  polyMesh& mesh = const_cast<polyMesh&>(pMesh);
311 
312 
313  for (const entry& dEntry : coeffsDict_)
314  {
315  if (!dEntry.isDict())
316  {
317  const word& key = dEntry.keyword();
318  const word value(dEntry.get<word>());
319 
320  Info<< typeName << " : setting parameter " << key
321  << " to " << value << endl;
322 
323  Zoltan_Set_Param(zz, key.c_str(), value.c_str());
324  }
325  }
326 
327 
328  Zoltan_Set_Num_Obj_Fn(zz, get_number_of_vertices, &mesh);
329  Zoltan_Set_Obj_List_Fn(zz, get_vertex_list, &mesh);
330 
331  // Callbacks for geometry
332  Zoltan_Set_Num_Geom_Fn(zz, get_mesh_dim, &mesh);
333  Zoltan_Set_Geom_Multi_Fn(zz, get_geom_list, &mesh);
334 
335  // Callbacks for connectivity
336  Zoltan_Set_Num_Edges_Multi_Fn(zz, get_num_edges_list, &mesh);
337  Zoltan_Set_Edge_List_Multi_Fn(zz, get_edge_list, &mesh);
338 
339 
340 
341  //Note: !global indices
342  List<ZOLTAN_ID_TYPE> wantedCells(mesh.nCells());
343 
344  globalIndex globalCells(mesh.nCells());
345  forAll(wantedCells, i)
346  {
347  //wantedCells[i] = i;
348  wantedCells[i] = globalCells.toGlobal(i);
349  }
350 
351  List<ZOLTAN_ID_TYPE> oldToNew(mesh.nCells());
352 
353  int err = Zoltan_Order
354  (
355  zz,
356  1, //int num_gid_entries,
357  mesh.globalData().nTotalCells(), //int num_obj,
358  wantedCells.begin(),
359  oldToNew.begin()
360  );
361 
362  if (err != ZOLTAN_OK)
363  {
365  << "Failed Zoltan_Order" << exit(FatalError);
366  }
367 
368 
369  for (label i = 0; i < argc; i++)
370  {
371  free(argv[i]);
372  }
373 
374 
375  labelList order(oldToNew.size());
376  forAll(order, i)
377  {
378  order[i] = oldToNew[i];
379  }
380  return order;
381 }
382 
383 
384 // ************************************************************************* //
static int get_mesh_dim(void *data, int *ierr)
dictionary dict
uint8_t direction
Definition: direction.H:46
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static void get_geom_list(void *data, int num_gid_entries, int num_lid_entries, int num_obj, ZOLTAN_ID_PTR global_ids, ZOLTAN_ID_PTR local_ids, int num_dim, double *geom_vec, int *ierr)
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
virtual labelList renumber(const pointField &) const
Return the order in which cells need to be visited (ie. from ordered back to original cell label)...
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
Abstract base class for renumbering.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
static void get_edge_list(void *data, int sizeGID, int sizeLID, int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int *num_edges, ZOLTAN_ID_PTR nborGID, int *nborProc, int wgt_dim, float *ewgts, int *ierr)
dynamicFvMesh & mesh
const pointField & points
System unsigned integer.
A class for handling words, derived from Foam::string.
Definition: word.H:63
label size() const noexcept
The number of arguments.
Definition: argListI.H:139
const globalMeshData & globalData() const
Return parallel info (demand-driven)
Definition: polyMesh.C:1311
Templated 3D Vector derived from VectorSpace adding construction from 3 components, element access using x(), y() and z() member functions and the inner-product (dot-product) and cross-product operators.
Definition: Vector.H:58
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
defineTypeNameAndDebug(combustionModel, 0)
label nTotalCells() const noexcept
Return total number of cells in decomposed mesh.
static int get_number_of_vertices(void *data, int *ierr)
static void get_vertex_list(void *data, int sizeGID, int sizeLID, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int wgt_dim, float *obj_wgts, int *ierr)
label nCells() const noexcept
Number of mesh cells.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:53
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
volScalarField & p
Foam::argList args(argc, argv)
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static void get_num_edges_list(void *data, int sizeGID, int sizeLID, int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int *numEdges, int *ierr)