NEMoSys  0.63.0
A modular, extensible resource with robust automated mesh generation, mesh quality analysis, adaptive mesh refinement, and data transfer between arbitrary meshes.
RocPartCommGenDriver.C
Go to the documentation of this file.
1 /*******************************************************************************
2 * Promesh *
3 * Copyright (C) 2022, IllinoisRocstar LLC. All rights reserved. *
4 * *
5 * Promesh is the property of IllinoisRocstar LLC. *
6 * *
7 * IllinoisRocstar LLC *
8 * Champaign, IL *
9 * www.illinoisrocstar.com *
10 * promesh@illinoisrocstar.com *
11 *******************************************************************************/
12 /*******************************************************************************
13 * This file is part of Promesh *
14 * *
15 * This version of Promesh is free software: you can redistribute it and/or *
16 * modify it under the terms of the GNU Lesser General Public License as *
17 * published by the Free Software Foundation, either version 3 of the License, *
18 * or (at your option) any later version. *
19 * *
20 * Promesh is distributed in the hope that it will be useful, but WITHOUT ANY *
21 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more *
23 * details. *
24 * *
25 * You should have received a copy of the GNU Lesser General Public License *
26 * along with this program. If not, see <https://www.gnu.org/licenses/>. *
27 * *
28 *******************************************************************************/
30 
31 #include "AuxiliaryFunctions.H"
32 #include "Drivers/TransferDriver.H"
33 #include "IO/cgnsWriter.H"
34 #include "Mesh/meshBase.H"
35 
36 #include <cgnslib.h>
37 #include <vtkAppendFilter.h>
38 #include <vtkCellData.h>
39 #include <vtkCleanPolyData.h>
40 #include <vtkEdgeTable.h>
41 #include <vtkGenericCell.h>
42 #include <vtkPointData.h>
43 #include <vtkPointLocator.h>
44 #include <vtkUnstructuredGrid.h>
45 
46 #include <iostream>
47 #include <map>
48 #include <memory>
49 #include <sstream>
50 #include <string>
51 #include <unordered_set>
52 #include <set>
53 #include <vector>
54 
55 namespace NEM {
56 namespace DRV {
57 
58 namespace {
59 
60 /**
61  * @brief Helper class to implement RocPartCommGenDriver
62  */
63 class RocPartCommGenRunner {
64  public:
65  /*
66  RocPartCommGenRunner(
67  std::shared_ptr<meshBase> vol, std::shared_ptr<meshBase> surf,
68  std::shared_ptr<meshBase> volWithSol,
69  std::shared_ptr<meshBase> surfWithSol,
70  std::shared_ptr<meshBase> burnSurfWithSol, int numPartitions,
71  const std::string &base_t, int writeIntermediateFiles,
72  double searchTolerance, const std::string &caseName,
73  const std::map<std::string, std::vector<int>> &surfacePatchTypes,
74  bool _withC2CTransSmooth = false,
75  const std::string &_prefix_path = std::string());
76  */
77  RocPartCommGenRunner(const std::string &volname, const std::string &surfname,
78  int numPartitions);
79  ~RocPartCommGenRunner();
80 
81  // --- executor functions
82  private:
83  // run the driver (called on construction)
84  void execute(int numPartitions);
85  // extract patches from each surface partition and get patch virtual cells
86  void extractPatches();
87  // add global cell ids to provided mesh (used to add to full surface)
88  void AddGlobalCellIds(std::shared_ptr<meshBase> mesh) const;
89  // find shared nodes and sent nodes/cells from me to other procs
90  void getGhostInformation(int me, bool vol);
91  // get global ids and maps which were loaded into vol mesh partitions during
92  // partitioning
93  void getGlobalIdsAndMaps(int numPartitions, bool vol);
94  // get virtual cells for complete (not patch) vol (vol=true) or surf
95  // (vol=false) partition
96  void getVirtualCells(int me, int you, bool vol);
97  // get the shared nodes between patches both intra- and inter-partition
98  void getSharedPatchInformation();
99 
100  // --- info for write to cgns and intermediaries
101  private:
102  // base time step (Rocstar convention, eg. 04.210000)
103  std::string base_t;
104  // trimmed time step (eg. 4.21)
105  std::string trimmed_base_t;
106  // if true, all intermediate files will be written (i.e. surf partitions,
107  // virtuals etc.)
109  // Rocstar case name, used to write Rocstar input file names
110  std::string caseName;
111 
112  // --- write cgns files
113  private:
114  // write vol cgns (proc is partition num, type is patch num, prefix usually
115  // fluid)
116  void writeVolCgns(const std::string &prefix, int proc, int type);
117  // write surf cgns (proc is partition num, other info is deduced from maps)
118  void writeSurfCgns(const std::string &prefix, int proc);
119  // void writeVolGs(const std::string& prefix, int proc, int type);
120  void writeVolCellFaces(const std::string &prefix, int proc, int type) const;
121 
122  // --- write Rocstar files
123  private:
124  // write region mapping file
125  void mapWriter() const;
126  // write cell mapping file
127  void cmpWriter(int proc, int nCells) const;
128  // write communication lists file
129  void comWriter(int proc) const;
130  // write dimensions file
131  void dimWriter(int proc, std::shared_ptr<meshBase> realMB,
132  std::shared_ptr<meshBase> totalMB) const;
133  // write surface information for dimensions file
134  void dimSurfWriter(int proc, const std::vector<cgsize_t> &cgConnReal,
135  const std::vector<cgsize_t> &cgConnVirtual, int patchNo);
136  void dimSurfWriter(int proc) const;
137  void dimSurfSort(int proc) const;
138  // write processor mapping file
139  void txtWriter() const;
140  // utilities
141 
142  // --- real and virtual meshes
143  private:
144  // remeshed volume to be partitioned
145  std::shared_ptr<meshBase> mesh;
146  // stitched surface
147  std::shared_ptr<meshBase> remeshedSurf;
148  // original volume mesh with solution data
149  std::shared_ptr<meshBase> volWithSol;
150  // original surface mesh with solution data
151  std::shared_ptr<meshBase> surfWithSol;
152  // original burning surface mesh with solution data (iburn)
153  std::shared_ptr<meshBase> burnSurfWithSol;
154  // TODO: add meshBase (mbObj[2] from remeshDriver) for iburn solution mesh
155  // (iBurnWithSol) figure out a way to extract the cells with bflag on
156  // each surf/vol partition transfer data from iBurnWithSol to surf
157  // partitions and write them out to cgns
158 
159  // partitions <proc, partition>
160  std::vector<std::shared_ptr<meshBase>> partitions;
161  // <proc, <proc, mesh>>
162  std::vector<std::map<int, std::shared_ptr<meshBase>>>
164  // surface partitions <proc, partition>
165  std::vector<std::shared_ptr<meshBase>> surfacePartitions;
166  // <proc, <proc, mesh>>
167  std::vector<std::map<int, std::shared_ptr<meshBase>>>
169  // <proc, <patch, mesh>>
170  std::vector<std::map<int, std::shared_ptr<meshBase>>>
172  // <proc, <proc, <patch, mesh>>>
173  std::vector<std::map<int, std::map<int, std::shared_ptr<meshBase>>>>
175 
176  // --- tolerance for cell and point search
177  private:
179 
180  // --- global to local node and cell index maps
181  // --- the following are cleared and reused for vol and surf partitions
182  private:
183  // global node indices of partition
184  std::vector<std::vector<nemId_t>> globalNodeIds;
185  // global cell indices of partition
186  std::vector<std::vector<nemId_t>> globalCellIds;
187  // <proc, <global nodeId, local nodeId>>
188  std::vector<std::map<nemId_t, nemId_t>> globToPartNodeMap;
189  // <proc, <global cellId, local cellId>>
190  std::vector<std::map<nemId_t, nemId_t>> globToPartCellMap;
191  // <proc, <local nodeId, global nodeId>>
192  std::vector<std::map<nemId_t, nemId_t>> partToGlobNodeMap;
193  // <proc, <local cellId, global cellId>>
194  std::vector<std::map<nemId_t, nemId_t>> partToGlobCellMap;
195 
196  // --- volume partition ghost information
197  private:
198  // <proc, <proc, shared nodes>>
199  std::map<int, std::map<int, std::vector<int>>> sharedNodes;
200  // <proc, <proc, sent nodes>>
201  std::map<int, std::map<int, std::unordered_set<int>>> sentNodes;
202  // <proc, <proc, sent cells>>
203  std::map<int, std::map<int, std::unordered_set<int>>> sentCells;
204  // <proc, <proc, received nodes>>
205  std::map<int, std::map<int, std::unordered_set<int>>> receivedNodes;
206  // <proc, <proc, received cells>>
207  std::map<int, std::map<int, std::unordered_set<int>>> receivedCells;
208 
209  // --- surface partition ghost information
210  private:
211  // <proc, <proc, shared nodes>>
212  std::map<int, std::map<int, std::vector<int>>> sharedSurfNodes;
213  // <proc, <proc, sent nodes>>
214  std::map<int, std::map<int, std::unordered_set<int>>> sentSurfNodes;
215  // <proc, <proc, sent cells>>
216  std::map<int, std::map<int, std::unordered_set<int>>> sentSurfCells;
217  // <proc, <proc, received nodes>>
218  std::map<int, std::map<int, std::unordered_set<int>>> receivedSurfNodes;
219  // <proc, <proc, received cells>>
220  std::map<int, std::map<int, std::unordered_set<int>>> receivedSurfCells;
221 
222  // --- patch comm information
223  private:
224  /* shared nodes b/w patches and proc [proc][patch][proc][patch]
225  eg) partition 0's patch i potentially shares with patch j on proc 0 and
226  possibly the other process */
227  std::vector<std::map<int, std::map<int, std::map<int, std::vector<int>>>>>
229 
230  // --- pconn vectors for vol and surf partitions
231  private:
232  // pconn for each vol partition
233  // <proc, pconns>
234  std::vector<std::vector<int>> volPconns;
235  // pconn for each patch of each surf partition
236  // <proc, <patch, pconns>>
237  std::vector<std::map<int, std::vector<int>>> surfPconns;
238  // maximum Pconn values for each proc
239  std::map<int, int> pconnProcMax;
240  // minimum Pconn values for each proc
241  std::map<int, int> pconnProcMin;
242 
243  // --- storing number of unique volumetric faces for each partition
244  // <proc, number of faces>
245  std::map<int, int> nUniqueVolFaces;
246 
247  // --- volume to surface node maps for each partition
248  private:
249  // Stores volume meshes with virtual for each proc
250  std::vector<std::shared_ptr<meshBase>> procVolMesh;
251 
252  // --- data transfer props
253  private:
255 
256  // --- other props
257  private:
258  std::string prefixPath;
259 
260  // --- write pconn information into pconn vectors
261  private:
262  // write shared pconn vec for vol partition proc - returns length
263  int writeSharedToPconn(int proc, const std::string &type);
264 
265  // write shared pconn vec for all patches in surf pconn proc
266  void writeSharedToPconn(int proc);
267  // write sent pconn vec for vol partition proc for nodes (nodeOrCell=true) and
268  // cells
269  void writeSentToPconn(int proc, const std::string &type, bool nodeOrCell);
270  // write received pconn vec for vol partition proc for nodes (nodeOrCell=true)
271  // and cells
272  void writeReceivedToPconn(int proc, const std::string &type, bool nodeOrCell);
273  // get shared nodes, sent nodes/cells, received nodes/cells for
274  // both partitions me and you
275  void getGhostInformation(int me, int you, bool hasShared, bool vol,
276  vtkSmartPointer<vtkIdList> cellIdsList,
277  vtkSmartPointer<vtkGenericCell> genCell);
278  // restructure Pconn information so that Rocstar can read it properly
279  void restructurePconn(std::vector<int> &pconnVec, int proc, int volOrSurf,
280  const std::map<int, int> &old2New, int &nGhost);
281  // Map old to new indices for point data
282  void mapOld2NewPointData(std::vector<double> &pointData,
283  const std::map<int, int> &new2Old) const;
284  // function for re-ordering tri indices
285  void swapTriOrdering(std::vector<cgsize_t> &connVec) const;
286 
287  private:
288  // --- temporary vectors to assist with writing out pconn info to Rocstar
289  // input files
290  std::vector<int> neighborProcsTmp;
291  std::map<int, std::vector<int>> sharedNodesTmp;
292  std::map<int, std::vector<int>> sentNodesTmp;
293  std::map<int, std::vector<int>> receivedNodesTmp;
294  std::map<int, std::vector<int>> sentCellsTmp;
295  std::map<int, std::vector<int>> receivedCellsTmp;
296  std::map<int, int> totalTrisPerPatch;
297  // Rocflu
298  // <proc<patch, zone>>
299  std::vector<std::map<int, int>> surfZoneMap;
300  // <proc, zone>
301  std::vector<int> volZoneMap;
302  // Rocburn
303  std::vector<std::map<int, int>> burnSurfZoneMap;
304  // Map of surface type to patch numbers
305  // <type, <patch>>
306  std::map<std::string, std::vector<int>> surfacePatchTypes;
307 
308  // --- utility to clear above vectors
309  private:
310  void clearPconnVectors();
311  void clearBorderVector();
312 
313  // --- descriptors for cgns writing
314  private:
315  std::vector<int> notGhostInPconn;
316 
317  // helpers
318  private:
319  /* deletes inter partition surfaces which result from extracting surface of
320  vol partition. this is done by comparing cells from full surface mesh to
321  extracted surface and removing those from the extracted surface which are
322  not found in the full surface */
323  vtkSmartPointer<vtkPolyData> deleteInterPartitionSurface(
324  std::shared_ptr<meshBase> fullSurf,
325  vtkSmartPointer<vtkDataSet> partSurf) const;
326  vtkSmartPointer<vtkEdgeTable> createPartitionEdgeTable(int i) const;
327 
328  // gets Patch type for each patch number
329  std::string getPatchType(int patchNo) const;
330 };
331 
332 /*
333 RocPartCommGenRunner::RocPartCommGenRunner(
334  std::shared_ptr<meshBase> _mesh, std::shared_ptr<meshBase> _remeshedSurf,
335  std::shared_ptr<meshBase> _volWithSol,
336  std::shared_ptr<meshBase> _surfWithSol,
337  std::shared_ptr<meshBase> _burnSurfWithSol, int numPartitions,
338  const std::string &_base_t, int _writeIntermediateFiles,
339  double _searchTolerance, const std::string &_caseName,
340  const std::map<std::string, std::vector<int>> &_surfacePatchTypes,
341  bool _withC2CTransSmooth, const std::string &_prefix_path) {
342  std::cout << "RocPartCommGenRunner created" << std::endl;
343 
344  // setting inputs
345  prefixPath = _prefix_path;
346  this->mesh = _mesh;
347 
348  // load stitched surf mesh with patch info
349  this->remeshedSurf = _remeshedSurf;
350  this->volWithSol = _volWithSol;
351  this->surfWithSol = _surfWithSol;
352  this->burnSurfWithSol = _burnSurfWithSol;
353  this->base_t = _base_t;
354  this->caseName = _caseName;
355  this->trimmed_base_t = std::to_string(std::stod(_base_t));
356  this->trimmed_base_t.erase(this->trimmed_base_t.find_last_not_of('0') + 1,
357  std::string::npos);
358  this->writeAllFiles = _writeIntermediateFiles;
359  this->searchTolerance = _searchTolerance;
360  this->surfacePatchTypes = _surfacePatchTypes;
361 
362  // transfer setting
363  this->smoothC2CTrans = _withC2CTransSmooth;
364  this->volWithSol->setContBool(this->smoothC2CTrans);
365 
366  // running
367  this->execute(numPartitions);
368 }
369 */
370 
371 RocPartCommGenRunner::RocPartCommGenRunner(const std::string &volname,
372  const std::string &surfname,
373  int numPartitions) {
374  std::cout << "RocPartCommGenRunner created" << std::endl;
375 
376  // load full volume mesh and create METIS partitions
377  prefixPath = std::string();
378  this->mesh = meshBase::CreateShared(volname);
379  this->remeshedSurf = meshBase::CreateShared(surfname);
380  this->base_t = "00.000000";
381  this->trimmed_base_t = "0.0";
382  this->writeAllFiles = 0;
383  this->execute(numPartitions);
384 }
385 
386 void RocPartCommGenRunner::execute(int numPartitions) {
387  std::cout << "executing" << std::endl;
388  remeshedSurf->setContBool(false);
389 
390  // breaking down to partitions
391  this->partitions = meshBase::partition(this->mesh.get(), numPartitions);
392  this->AddGlobalCellIds(this->remeshedSurf);
393  std::vector<std::string> paneDataAndGlobalCellIds = {
394  "patchNo", "bcflag", "cnstr_type", "GlobalCellIds"};
395 
396  // initialize storage for surf partitions
397  vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid;
398  this->surfacePartitions.resize(numPartitions, nullptr);
399 
400  // initialize storage for virtual cells
401  this->virtualCellsOfPartitions.resize(numPartitions);
402  this->virtualCellsOfSurfPartitions.resize(numPartitions);
403 
404  // get all required local-global node maps and node/cell ids
405  std::cout << "getting maps" << std::endl;
406  this->getGlobalIdsAndMaps(numPartitions, true);
407 
408  // allocate storage for vol pconn vectors
409  this->volPconns.resize(numPartitions);
410  this->notGhostInPconn.resize(numPartitions);
411 
412  // processing surface partitions for next steps
413  // generating volumetric CGNS files
414  for (int i = 0; i < numPartitions; ++i) {
415  vtkSmartPointer<vtkAppendFilter> appendFilter =
417  appendFilter->AddInputData(deleteInterPartitionSurface(
418  remeshedSurf, partitions[i]->extractSurface()));
419  appendFilter->Update();
420 
421  // create surfs partitions casted from vtp to vtu
422  unstructuredGrid = appendFilter->GetOutput();
423  std::string basename(prefixPath + "surfacePartition");
424  basename += std::to_string(i);
425  basename += ".vtu";
426 
427  // construct meshBase surface partition from vtkUnstructuredGrid
428  // and transfer some pane data
429  this->surfacePartitions[i] =
430  meshBase::CreateShared(unstructuredGrid, basename);
431 
432  /*
433  remeshedSurf->transfer(this->surfacePartitions[i].get(),
434  "Consistent Interpolation",
435  paneDataAndGlobalCellIds,
436  true);
437  */
438  auto transfer = TransferDriver::CreateTransferObject(
439  remeshedSurf.get(), this->surfacePartitions[i].get(),
440  "Consistent Interpolation");
441  transfer->transferCellData(paneDataAndGlobalCellIds,
442  remeshedSurf->getNewArrayNames());
443 
444  if (this->writeAllFiles > 0) this->surfacePartitions[i]->write();
445 
446  // get ghost information for volume partitions
447  this->getGhostInformation(i, true);
448 
449  // write pconn information for volume partition
450  std::string type("01");
451  notGhostInPconn[i] = this->writeSharedToPconn(i, type);
452  this->writeSentToPconn(i, type, true);
453  this->writeReceivedToPconn(i, type, true);
454  this->writeSentToPconn(i, type, false);
455  this->writeReceivedToPconn(i, type, false);
456  this->comWriter(i + 1);
457 
458  // get virtual cells of each volume partition (t4:virtual)
459  // for current partition
460  for (int j = 0; j < numPartitions; ++j) this->getVirtualCells(i, j, true);
461 
462  // write cgns for vol partition
463  this->writeVolCgns("fluid", i, 1);
464  this->clearPconnVectors();
465  }
466 
467  // write cell mapping file for entire mesh
468  this->cmpWriter(0, this->mesh->getDataSet()->GetNumberOfCells());
469  // write dimension file for entire mesh
470  this->dimWriter(0, this->mesh, this->mesh);
471 
472  // get global ids and maps for surface partitions
473  this->getGlobalIdsAndMaps(numPartitions, false);
474  for (int i = 0; i < numPartitions; ++i) {
475  // get ghost information for each surface partition
476  this->getGhostInformation(i, false);
477  // get virtual cells for each surface partition (t3:virtual)
478  for (int j = 0; j < numPartitions; ++j) {
479  this->getVirtualCells(i, j, false);
480  }
481  }
482 
483  // extract patches of each partition and get virtual cells from patches in
484  // other partitions for each partition
485  this->extractPatches();
486 
487  // allocate shared patch nodes 4d map
488  this->sharedPatchNodes.resize(numPartitions);
489 
490  // get shared nodes between patches both intra- and inter-partition
491  this->getSharedPatchInformation();
492 
493  // allocate storage for surf pconn vectors
494  this->surfPconns.resize(numPartitions);
495 
496  // determining patch to zone numbers for surfaces
497  // before writing surface Pconns
498  std::map<int, int> surfZoneNumbersMap;
499  for (int iProc = 0; iProc < numPartitions; ++iProc) {
500  int zoneCounter = 2; // first zone is always volume
501  surfZoneNumbersMap.clear();
502 
503  auto it = this->sharedPatchNodes[iProc].begin(); // patch
504  while (it != sharedPatchNodes[iProc].end()) {
505  surfZoneNumbersMap[it->first] = zoneCounter;
506  zoneCounter += 1;
507  ++it;
508  }
509  surfZoneMap.push_back(surfZoneNumbersMap);
510  }
511  for (int i = 0; i < numPartitions; ++i) {
512  this->writeSharedToPconn(i);
513  std::cout << "writing rocflu ifluid_b cgns files" << std::endl;
514  this->writeSurfCgns("ifluid_b", i);
515  std::cout << "writing rocflu ifluid_ni cgns files" << std::endl;
516  this->writeSurfCgns("ifluid_ni", i);
517  std::cout << "writing rocflu ifluid_nb cgns files" << std::endl;
518  this->writeSurfCgns("ifluid_nb", i);
519  std::cout << "writing rocburn burn cgns files" << std::endl;
520  this->writeSurfCgns("burn", i);
521  std::cout << "writing rocburn iburn_all files" << std::endl;
522  this->writeSurfCgns("iburn_all", i);
523  }
524  // writing rocflu dim files
525  this->dimSurfWriter(0);
526  for (int i = 0; i < numPartitions; ++i) {
527  this->dimSurfSort(i);
528  }
529 
530  // writing rocin pane/window info files
531  this->txtWriter();
532 
533  // write number of cell faces for each volume partition
534  // Note: This is only interior cell faces, i.e. volume cell faces - surface
535  // cell faces
536  this->getGlobalIdsAndMaps(numPartitions, true);
537  for (int i = 0; i < numPartitions; ++i) {
538  // write CGNS for vol partition
539  this->writeVolCellFaces("fluid", i, 1);
540  }
541 
542  // writing rocflu map files
543  this->mapWriter();
544 }
545 
546 void RocPartCommGenRunner::AddGlobalCellIds(
547  std::shared_ptr<meshBase> _mesh) const {
548  vtkSmartPointer<vtkDataArray> globalCellIds =
550  globalCellIds->SetName("GlobalCellIds");
551  globalCellIds->SetNumberOfComponents(1);
552  globalCellIds->SetNumberOfTuples(_mesh->getNumberOfCells());
553  for (int i = 0; i < _mesh->getNumberOfCells(); ++i)
554  globalCellIds->SetTuple1(i, i);
555  _mesh->getDataSet()->GetCellData()->AddArray(globalCellIds);
556 }
557 
558 void RocPartCommGenRunner::getGlobalIdsAndMaps(int numPartitions, bool vol) {
559  // clear vectors before use
560  this->globToPartNodeMap.clear();
561  this->globToPartCellMap.clear();
562  this->partToGlobNodeMap.clear();
563  this->partToGlobCellMap.clear();
564  this->globalNodeIds.clear();
565  this->globalCellIds.clear();
566 
567  // allocate
568  this->globToPartNodeMap.resize(numPartitions);
569  this->globToPartCellMap.resize(numPartitions);
570  this->partToGlobNodeMap.resize(numPartitions);
571  this->partToGlobCellMap.resize(numPartitions);
572  this->globalNodeIds.resize(numPartitions);
573  this->globalCellIds.resize(numPartitions);
574 
575  // get preloaded maps if volume
576  if (vol) {
577  for (int i = 0; i < numPartitions; ++i) {
578  this->globToPartNodeMap[i] = partitions[i]->getGlobToPartNodeMap();
579  this->globToPartCellMap[i] = partitions[i]->getGlobToPartCellMap();
580  this->partToGlobNodeMap[i] = partitions[i]->getPartToGlobNodeMap();
581  this->partToGlobCellMap[i] = partitions[i]->getPartToGlobCellMap();
582  this->globalNodeIds[i] =
584  this->globalCellIds[i] =
586  }
587  }
588  // compute maps and set if surface
589  else {
590  for (int i = 0; i < numPartitions; ++i) {
591  vtkSmartPointer<vtkDataArray> globalNodeIds =
592  surfacePartitions[i]->getDataSet()->GetPointData()->GetArray(
593  "GlobalNodeIds");
594  for (int j = 0; j < surfacePartitions[i]->getNumberOfPoints(); ++j) {
595  int globNodeId = static_cast<int>(globalNodeIds->GetTuple1(j));
596  this->globToPartNodeMap[i][globNodeId] = j;
597  this->partToGlobNodeMap[i][j] = globNodeId;
598  }
599  vtkSmartPointer<vtkDataArray> globalCellIds =
600  surfacePartitions[i]->getDataSet()->GetCellData()->GetArray(
601  "GlobalCellIds");
602  for (int j = 0; j < surfacePartitions[i]->getNumberOfCells(); ++j) {
603  int globCellId = static_cast<int>(globalCellIds->GetTuple1(j));
604  this->globToPartCellMap[i][globCellId] = j;
605  this->partToGlobCellMap[i][j] = globCellId;
606  }
607  this->globalNodeIds[i] =
609  this->globalCellIds[i] =
611  }
612  }
613 }
614 
615 int RocPartCommGenRunner::writeSharedToPconn(int proc,
616  const std::string &type) {
617  auto sharedItr = this->sharedNodes[proc].begin();
618  while (sharedItr != this->sharedNodes[proc].end()) {
619  if (sharedItr->second.size() != 0) {
620  // num blocks
621  this->volPconns[proc].push_back(1);
622  this->neighborProcsTmp.push_back(sharedItr->first);
623  std::stringstream ss;
624  ss << sharedItr->first + 1 << type;
625 
626  // zone number
627  this->volPconns[proc].push_back(std::stoi(ss.str()));
628 
629  // number of ids
630  this->volPconns[proc].push_back(sharedItr->second.size());
631 
632  // indices
633  std::vector<int> tmpInd;
634  for (int i = 0; i < sharedItr->second.size(); ++i) {
635  this->volPconns[proc].push_back(sharedItr->second[i] + 1);
636  tmpInd.push_back(sharedItr->second[i] + 1);
637  }
638  this->sharedNodesTmp[sharedItr->first] = tmpInd;
639  }
640  ++sharedItr;
641  }
642  return volPconns[proc].size();
643 }
644 
645 void RocPartCommGenRunner::writeSharedToPconn(int proc) {
646  auto it = this->sharedPatchNodes[proc].begin(); // patch
647  while (it != sharedPatchNodes[proc].end()) {
648  auto it1 = it->second.begin(); // proc
649  while (it1 != it->second.end()) {
650  auto it2 = it1->second.begin(); // patch
651  while (it2 != it1->second.end()) {
652  if (it2->second.size() > 0) {
653  this->surfPconns[proc][it->first].push_back(1);
654  // zone number
655  std::stringstream ss;
656  ss << it1->first + 1 << ((it->first + 1) < 10 ? "0" : "")
657  << this->surfZoneMap[it1->first][it2->first];
658  this->surfPconns[proc][it->first].push_back(std::stoi(ss.str()));
659  // num blocks for this proc and current patch
660  if (it2->second.size() > 0) {
661  // number of ids
662  this->surfPconns[proc][it->first].push_back(it2->second.size());
663  for (int k = 0; k < it2->second.size(); ++k) {
664  this->surfPconns[proc][it->first].push_back(it2->second[k] + 1);
665  }
666  } else {
667  this->surfPconns[proc][it->first].push_back(0);
668  }
669  }
670  ++it2;
671  }
672  ++it1;
673  }
674  ++it;
675  }
676 }
677 
678 void RocPartCommGenRunner::writeSentToPconn(int proc, const std::string &type,
679  bool nodeOrCell) {
680  std::map<int, std::unordered_set<int>>::iterator sentItr;
681  std::map<int, std::unordered_set<int>>::iterator end;
682 
683  if (nodeOrCell) {
684  sentItr = this->sentNodes[proc].begin();
685  end = this->sentNodes[proc].end();
686  } else {
687  sentItr = this->sentCells[proc].begin();
688  end = this->sentCells[proc].end();
689  }
690  std::vector<int> tmpInd;
691  while (sentItr != end) {
692  if (sentItr->second.size() != 0) {
693  // num blocks
694  this->volPconns[proc].push_back(1);
695 
696  std::stringstream ss;
697  ss << sentItr->first + 1 << type;
698 
699  // zone number
700  this->volPconns[proc].push_back(std::stoi(ss.str()));
701 
702  // number of ids
703  this->volPconns[proc].push_back(sentItr->second.size());
704 
705  // nodes
706  if (nodeOrCell) {
707  // Sort by global ID
708  std::vector<std::pair<int, int>> sentNodesIdPairs;
709  for (auto itr = sentItr->second.begin(); itr != sentItr->second.end();
710  ++itr) {
711  sentNodesIdPairs.push_back(
712  std::make_pair(partToGlobNodeMap[proc][*itr], *itr));
713  }
714  std::sort(sentNodesIdPairs.begin(), sentNodesIdPairs.end());
715  std::vector<int> sentNodesSorted;
716  for (auto itr = sentNodesIdPairs.begin(); itr != sentNodesIdPairs.end();
717  ++itr) {
718  sentNodesSorted.push_back((*itr).second);
719  }
720 
721  auto tmpIt = sentNodesSorted.begin();
722  tmpInd.clear();
723  while (tmpIt != sentNodesSorted.end()) {
724  this->volPconns[proc].push_back(*tmpIt + 1);
725  tmpInd.push_back(*tmpIt + 1);
726  ++tmpIt;
727  }
728  }
729  // cells
730  else {
731  // Sort by global ID
732  std::vector<std::pair<int, int>> sentCellsIdPairs;
733  for (auto itr = sentItr->second.begin(); itr != sentItr->second.end();
734  ++itr) {
735  sentCellsIdPairs.push_back(
736  std::make_pair(partToGlobCellMap[proc][*itr], *itr));
737  }
738  std::sort(sentCellsIdPairs.begin(), sentCellsIdPairs.end());
739  std::vector<int> sentCellsSorted;
740  for (auto itr = sentCellsIdPairs.begin(); itr != sentCellsIdPairs.end();
741  ++itr) {
742  sentCellsSorted.push_back((*itr).second);
743  }
744 
745  auto tmpIt = sentCellsSorted.begin();
746  tmpInd.clear();
747  while (tmpIt != sentCellsSorted.end()) {
748  this->volPconns[proc].push_back(*tmpIt + 1);
749  tmpInd.push_back(*tmpIt + 1);
750  ++tmpIt;
751  }
752  }
753 
754  if (nodeOrCell) {
755  this->sentNodesTmp[sentItr->first] = tmpInd;
756  } else {
757  this->sentCellsTmp[sentItr->first] = tmpInd;
758  }
759  }
760  ++sentItr;
761  }
762 }
763 
764 void RocPartCommGenRunner::writeReceivedToPconn(int proc,
765  const std::string &type,
766  bool nodeOrCell) {
767  std::map<int, std::unordered_set<int>>::iterator receivedItr;
768  std::map<int, std::unordered_set<int>>::iterator end;
769 
770  int offset;
771 
772  // nodes
773  if (nodeOrCell) {
774  receivedItr = this->receivedNodes[proc].begin();
775  end = this->receivedNodes[proc].end();
776  offset = partitions[proc]->getNumberOfPoints();
777  }
778  // cells
779  else {
780  receivedItr = this->receivedCells[proc].begin();
781  end = this->receivedCells[proc].end();
782  offset = partitions[proc]->getNumberOfCells();
783  }
784 
785  // keep tally of previously received for virtual indexing
786  int numPrevReceived = 0;
787 
788  std::vector<int> tmpInd;
789 
790  // map of received node IDs to local indexing
791  // This prevents duplicate nodes being added to pconn if we receive
792  // the same virtual node from two different procs
793  std::map<int, int> receivedNodeMap;
794 
795  while (receivedItr != end) {
796  if (receivedItr->second.size() != 0) {
797  // num blocks
798  this->volPconns[proc].push_back(1);
799  std::stringstream ss;
800  ss << receivedItr->first + 1 << type;
801 
802  // zone number
803  this->volPconns[proc].push_back(std::stoi(ss.str()));
804 
805  // number of ids;
806  int numReceived = 0;
807  int numDuplicates = 0;
808  this->volPconns[proc].push_back(receivedItr->second.size());
809  tmpInd.clear();
810 
811  for (auto itr = (receivedItr->second).begin();
812  itr != (receivedItr->second).end(); ++itr) {
813  if (receivedNodeMap.find(*itr) == receivedNodeMap.end()) {
814  receivedNodeMap[*itr] =
815  offset + numPrevReceived +
816  std::distance((receivedItr->second).begin(), itr) + 1 -
817  numDuplicates;
818  this->volPconns[proc].push_back(
819  offset + numPrevReceived +
820  std::distance((receivedItr->second).begin(), itr) + 1 -
821  numDuplicates);
822  tmpInd.push_back(offset + numPrevReceived +
823  std::distance((receivedItr->second).begin(), itr) +
824  1 - numDuplicates);
825  numReceived += 1;
826  } else {
827  this->volPconns[proc].push_back(receivedNodeMap[*itr]);
828  tmpInd.push_back(receivedNodeMap[*itr]);
829  numDuplicates += 1;
830  }
831  }
832  if (nodeOrCell) {
833  this->receivedNodesTmp[receivedItr->first] = tmpInd;
834  } else {
835  this->receivedCellsTmp[receivedItr->first] = tmpInd;
836  }
837  numPrevReceived += numReceived;
838  }
839  ++receivedItr;
840  }
841 }
842 
843 void RocPartCommGenRunner::getVirtualCells(int me, int you, bool vol) {
844  if (vol && this->sharedNodes[me][you].size()) {
845  std::vector<nemId_t> virtuals(receivedCells[me][you].begin(),
846  receivedCells[me][you].end());
848  meshBase::extractSelectedCells(this->mesh.get(), virtuals));
849  if (this->writeAllFiles > 0) {
850  std::stringstream ss;
851  ss << prefixPath << "virtual"
852  << "Vol"
853  << "Of" << me << "from" << you << ".vtu";
854  this->virtualCellsOfPartitions[me][you]->write(ss.str());
855  }
856  } else if (!vol && this->sharedSurfNodes[me][you].size()) {
857  std::vector<nemId_t> virtuals(receivedSurfCells[me][you].begin(),
858  receivedSurfCells[me][you].end());
860  meshBase::extractSelectedCells(this->remeshedSurf.get(), virtuals));
861  if (this->writeAllFiles > 0) {
862  std::stringstream ss;
863  ss << prefixPath << "virtual"
864  << "Surf"
865  << "Of" << me << "from" << you << ".vtu";
866  this->virtualCellsOfSurfPartitions[me][you]->write(ss.str());
867  }
868  }
869 }
870 
871 void RocPartCommGenRunner::getGhostInformation(int me, bool volOrSurf) {
872  // will hold sent cell's indices
873  vtkSmartPointer<vtkIdList> cellIdsList = vtkSmartPointer<vtkIdList>::New();
874  vtkSmartPointer<vtkGenericCell> genCell =
876 
877  // loop over all other procs to get nodes shared and nodes/cells sent
878  for (int you = 0; you < partitions.size(); ++you) {
879  if (you != me) {
880  this->getGhostInformation(me, you, false, volOrSurf, cellIdsList,
881  genCell);
882  this->getGhostInformation(you, me, true, volOrSurf, cellIdsList, genCell);
883  }
884  }
885 }
886 
887 void RocPartCommGenRunner::getGhostInformation(
888  int me, int you, bool hasShared, bool vol,
889  vtkSmartPointer<vtkIdList> cellIdsList,
890  vtkSmartPointer<vtkGenericCell> genCell) {
891  // need the volume mesh to determine which ghost cells are included in the
892  // surface
893  vtkSmartPointer<vtkIdList> volCellIdsList;
894  meshBase *meMesh;
895  meshBase *meVolMesh;
896  if (vol) {
897  meMesh = partitions[me].get();
898  } else {
899  meMesh = surfacePartitions[me].get();
900  meVolMesh = partitions[me].get();
901  }
902 
903  // ------ shared nodes between me and proc i
904  // compute the intersection and assign to sharedNodes vec
905  std::vector<int> tmpVec;
906  std::set_intersection(globalNodeIds[me].begin(), globalNodeIds[me].end(),
907  globalNodeIds[you].begin(), globalNodeIds[you].end(),
908  std::back_inserter(tmpVec));
909 
910  if (!hasShared) {
911  if (vol) {
912  this->sharedNodes[me][you].resize(tmpVec.size());
913  this->sharedNodes[you][me].resize(tmpVec.size());
914  } else {
915  this->sharedSurfNodes[me][you].resize(tmpVec.size());
916  this->sharedSurfNodes[you][me].resize(tmpVec.size());
917  }
918  }
919 
920  // ------ fill shared nodes map and find cells and nodes me sends to proc i
921  for (int j = 0; j < tmpVec.size(); ++j) {
922  // get local idx of shared node in me
923  int localPntId = globToPartNodeMap[me][tmpVec[j]];
924  // add to sharedNodes maps for you and me
925  if (!hasShared) {
926  int procLocalPntId;
927  if (vol) {
928  this->sharedNodes[me][you][j] = localPntId;
929  // get local idx of shared node in you
930  procLocalPntId = globToPartNodeMap[you][tmpVec[j]];
931  this->sharedNodes[you][me][j] = procLocalPntId;
932  } else {
933  this->sharedSurfNodes[me][you][j] = localPntId;
934  // get local idx of shared node in you
935  procLocalPntId = globToPartNodeMap[you][tmpVec[j]];
936  this->sharedSurfNodes[you][me][j] = procLocalPntId;
937  }
938  }
939 
940  cellIdsList->Reset();
941 
942  // find cells using this shared node
943  meMesh->getDataSet()->GetPointCells(localPntId, cellIdsList);
944 
945  // Nodes that are not shared among partitions
946  std::vector<int> notSharedCellNodes;
947 
948  // Surface nodes that are not shared with the volume ghost cells's nodes
949  std::vector<int> notSharedWithVolSurfNodes;
950 
951  // vtkIdList for checking if surface nodes are in volume mesh
952  vtkSmartPointer<vtkIdList> result = vtkSmartPointer<vtkIdList>::New();
953 
954  vtkSmartPointer<vtkPointLocator> pointLocator =
956 
957  // for each cell using shared node (these will be cells on the boundary)
958  for (int k = 0; k < cellIdsList->GetNumberOfIds(); ++k) {
959  // get the local cell idx
960  int localCellId = cellIdsList->GetId(k);
961 
962  // get the cell in me for point extraction
963  meMesh->getDataSet()->GetCell(localCellId, genCell);
964 
965  int numSharedInCell = 0;
966  vtkSmartPointer<vtkPolyData> virtualNodesSet =
968  std::vector<int> virtualNodesIdList;
969  if (!vol) {
970  // Construct a list of all volume ghost points. These will be compared
971  // against the surface cells because ghost surface cells are a subset of
972  // ghost volume cells.
973  vtkSmartPointer<vtkIdList> cellPoints =
975  vtkSmartPointer<vtkPoints> virtualNodesList =
977 
978  // Construct a vtkDataSet of only the sentCells
979  for (auto itr = sentCells[me][you].begin();
980  itr != sentCells[me][you].end(); ++itr) {
981  meVolMesh->getDataSet()->GetCellPoints((*itr), cellPoints);
982  for (int ipt = 0; ipt < cellPoints->GetNumberOfIds(); ipt++) {
983  virtualNodesList->InsertNextPoint(
984  meVolMesh->getDataSet()->GetPoint(cellPoints->GetId(ipt)));
985  virtualNodesIdList.push_back(cellPoints->GetId(ipt));
986  }
987  }
988  virtualNodesSet->SetPoints(virtualNodesList);
989  }
990 
991  // Clear lists of nodes
992  notSharedCellNodes.clear();
993  notSharedWithVolSurfNodes.clear();
994 
995  // Keep track of virtual volume cell Ids that contain each potential
996  // virtual surface point Id
997  std::vector<int> virtVolCellIds;
998  virtVolCellIds.clear();
999 
1000  for (int l = 0; l < genCell->GetNumberOfPoints(); ++l) {
1001  // get node idx of cell point
1002  int pntId = genCell->GetPointId(l);
1003 
1004  // if node is not found in shared nodes, it is sent
1005  int globPntId = this->partToGlobNodeMap[me][pntId];
1006 
1007  if (std::find(tmpVec.begin(), tmpVec.end(), globPntId) ==
1008  tmpVec.end()) {
1009  if (vol) {
1010  notSharedCellNodes.push_back(pntId);
1011  } else {
1012  double *pntCoor = meMesh->getDataSet()->GetPoint(pntId);
1013  if (virtualNodesSet->GetNumberOfPoints() > 0) {
1014  pointLocator->SetDataSet(virtualNodesSet);
1015  pointLocator->AutomaticOn();
1016  pointLocator->BuildLocator();
1017 
1018  result->Reset();
1019  pointLocator->FindPointsWithinRadius(this->searchTolerance,
1020  pntCoor, result);
1021  if (result->GetNumberOfIds()) {
1022  // add idx to map of nodes me sends to you
1023  this->sentSurfNodes[me][you].insert(pntId);
1024 
1025  // add idx to map of nodes you recevies from proc me
1026  this->receivedSurfNodes[you][me].insert(
1027  this->globToPartNodeMap
1028  [you][this->partToGlobNodeMap[me][pntId]]);
1029 
1030  std::vector<int> virtVolCellIdsTmp;
1031  virtVolCellIdsTmp.clear();
1032  for (int i = 0; i < result->GetNumberOfIds(); i++) {
1033  vtkSmartPointer<vtkIdList> myList =
1035  meVolMesh->getDataSet()->GetPointCells(
1036  virtualNodesIdList[result->GetId(i)], myList);
1037  for (int i = 0; i < myList->GetNumberOfIds(); i++) {
1038  virtVolCellIdsTmp.push_back(myList->GetId(i));
1039  }
1040  }
1041 
1042  // remove duplicates
1043  sort(virtVolCellIdsTmp.begin(), virtVolCellIdsTmp.end());
1044  virtVolCellIdsTmp.erase(
1045  unique(virtVolCellIdsTmp.begin(), virtVolCellIdsTmp.end()),
1046  virtVolCellIdsTmp.end());
1047  for (int &itr : virtVolCellIdsTmp) {
1048  virtVolCellIds.push_back(itr);
1049  }
1050  }
1051  } else {
1052  notSharedWithVolSurfNodes.push_back(pntId);
1053  }
1054  }
1055  } else {
1056  numSharedInCell += 1;
1057 
1058  if (!vol) {
1059  double *pntCoor = meMesh->getDataSet()->GetPoint(pntId);
1060  if (virtualNodesSet->GetNumberOfPoints() > 0) {
1061  pointLocator->SetDataSet(virtualNodesSet);
1062  pointLocator->AutomaticOn();
1063  pointLocator->BuildLocator();
1064 
1065  result->Reset();
1066  pointLocator->FindPointsWithinRadius(this->searchTolerance,
1067  pntCoor, result);
1068  if (result->GetNumberOfIds()) {
1069  // add idx to map of nodes me sends to you
1070  this->sentSurfNodes[me][you].insert(pntId);
1071 
1072  // add idx to map of nodes you recevies from proc me
1073  this->receivedSurfNodes[you][me].insert(
1074  this->globToPartNodeMap
1075  [you][this->partToGlobNodeMap[me][pntId]]);
1076 
1077  std::vector<int> virtVolCellIdsTmp;
1078  virtVolCellIdsTmp.clear();
1079  for (int i = 0; i < result->GetNumberOfIds(); i++) {
1080  vtkSmartPointer<vtkIdList> myList =
1082  meVolMesh->getDataSet()->GetPointCells(
1083  virtualNodesIdList[result->GetId(i)], myList);
1084  for (int i = 0; i < myList->GetNumberOfIds(); i++) {
1085  virtVolCellIdsTmp.push_back(myList->GetId(i));
1086  }
1087  }
1088  // remove duplicates
1089  sort(virtVolCellIdsTmp.begin(), virtVolCellIdsTmp.end());
1090  virtVolCellIdsTmp.erase(
1091  unique(virtVolCellIdsTmp.begin(), virtVolCellIdsTmp.end()),
1092  virtVolCellIdsTmp.end());
1093  for (int &itr : virtVolCellIdsTmp) {
1094  virtVolCellIds.push_back(itr);
1095  }
1096  }
1097  } else {
1098  notSharedWithVolSurfNodes.push_back(pntId);
1099  }
1100  }
1101  }
1102  if (vol && numSharedInCell >= 3) {
1103  // Add sent nodes only if the node belongs to a sent volume cell
1104  for (auto itr = notSharedCellNodes.begin();
1105  itr != notSharedCellNodes.end(); itr++) {
1106  // add idx to map of nodes me sends to you
1107  this->sentNodes[me][you].insert(*itr);
1108 
1109  // add idx to map of nodes you recevies from proc me
1110  this->receivedNodes[you][me].insert(
1111  this->partToGlobNodeMap[me][*itr]);
1112  }
1113  }
1114  }
1115 
1116  // sort list of accumulated virtual volume cell Ids that the potential
1117  // virtual surface node points belong to, and determine if all 3 (for
1118  // tets) share a single cell
1119  int currId = -1;
1120  int accum = 0;
1121  int accumMax = 0;
1122  if (!vol) {
1123  std::sort(virtVolCellIds.begin(), virtVolCellIds.end());
1124  // Remove cells that aren't a part of the virtual sent cells
1125  std::vector<int> virtVolCellIdsTmp;
1126  for (auto itr = virtVolCellIds.begin(); itr != virtVolCellIds.end();
1127  ++itr) {
1128  if (std::find(sentCells[me][you].begin(), sentCells[me][you].end(),
1129  *itr) != sentCells[me][you].end()) {
1130  virtVolCellIdsTmp.push_back(*itr);
1131  }
1132  }
1133  virtVolCellIds = virtVolCellIdsTmp;
1134 
1135  for (auto itr = virtVolCellIds.begin(); itr != virtVolCellIds.end();
1136  ++itr) {
1137  if (*itr != currId) {
1138  currId = *itr;
1139  accum = 0;
1140  }
1141  accum += 1;
1142  if (accum > accumMax) {
1143  accumMax = accum;
1144  }
1145  }
1146  }
1147  if (vol && numSharedInCell >= 3) {
1148  // add idx to sentCells to you map
1149  this->sentCells[me][you].insert(localCellId);
1150 
1151  // get the global cell index
1152  int globId = partToGlobCellMap[me][localCellId];
1153 
1154  // add idx to map of cells proc you recieves from proc me
1155  this->receivedCells[you][me].insert(globId);
1156  } else if (!vol && numSharedInCell >= 2 &&
1157  notSharedWithVolSurfNodes.empty() && accumMax == 3) {
1158  int globId = partToGlobCellMap[me][localCellId];
1159  this->sentSurfCells[me][you].insert(localCellId);
1160 
1161  // add idx to map of cells proc you recieves from proc me
1162  this->receivedSurfCells[you][me].insert(globId);
1163  }
1164  }
1165  }
1166 
1167  // Removing false positive cells (cells with three shared node and zero shared
1168  // face with the partition).
1169  // Strategy: all real virtual cells should have at least a face shared with
1170  // current partition
1171  if (vol) {
1172  // create an edge table for the other partition
1173  vtkSmartPointer<vtkEdgeTable> eTab = createPartitionEdgeTable(you);
1174  if (!eTab) {
1175  std::cerr << "Problem in building partition edge table." << std::endl;
1176  }
1177 
1178  std::vector<int> rmvLst;
1179  for (auto icId = sentCells[me][you].begin();
1180  icId != sentCells[me][you].end(); icId++) {
1181  // get all edges of the cells and make sure at least three are
1182  // shared with the current partition
1183  std::map<nemId_t, std::vector<double>> cellPntIdCrd =
1184  partitions[me]->getCell(*icId);
1185 
1186  // loop through point pairs
1187  int nShrEdg = 0;
1188  for (auto iid1 = cellPntIdCrd.begin(); iid1 != cellPntIdCrd.end();
1189  iid1++) {
1190  for (auto iid2 = std::next(iid1, 1); iid2 != cellPntIdCrd.end();
1191  iid2++) {
1192  // convert to process local
1193  int pntId1 = partToGlobNodeMap[me][iid1->first];
1194  int pntId2 = partToGlobNodeMap[me][iid2->first];
1195  if ((eTab->IsEdge(globToPartNodeMap[you][pntId1],
1196  globToPartNodeMap[you][pntId2])) > 0)
1197  nShrEdg++;
1198  }
1199  }
1200  if (nShrEdg < 3) rmvLst.push_back(*icId);
1201  }
1202  // std::cout << " Number of false positive virtual volume cells to remove "
1203  // << rmvLst.size() << std::endl;
1204  for (auto icId = rmvLst.begin(); icId != rmvLst.end(); icId++) {
1205  // std::cout << "removing cell " << *icId << std::endl;
1206  sentCells[me][you].erase(*icId);
1207  int globId = partToGlobCellMap[me][*icId];
1208  this->receivedCells[you][me].erase(globId);
1209  }
1210 
1211  // Also remove 'false positive' sent nodes if they are contained ONLY within
1212  // the cells in rmvLst (see above). We do this because it is possible for a
1213  // ndoe to belong to both a cell that we're sending and not sending.
1214  bool inRmvCell, inSentCell;
1215  std::vector<int> rmvNodeLst;
1216  for (auto inId = sentNodes[me][you].begin();
1217  inId != sentNodes[me][you].end(); inId++) {
1218  inRmvCell = false;
1219  inSentCell = false;
1220  for (auto icId = rmvLst.begin(); icId != rmvLst.end(); icId++) {
1221  vtkSmartPointer<vtkIdList> cellPtIds =
1223  cellPtIds = partitions[me]->getDataSet()->GetCell(*icId)->GetPointIds();
1224  int numCellPts = cellPtIds->GetNumberOfIds();
1225  for (int i = 0; i < numCellPts; ++i) {
1226  int ptId = cellPtIds->GetId(i);
1227  if (ptId == *inId) {
1228  inRmvCell = true;
1229  }
1230  }
1231  }
1232  for (auto icId = sentCells[me][you].begin();
1233  icId != sentCells[me][you].end(); icId++) {
1234  vtkSmartPointer<vtkIdList> cellPtIds =
1236  cellPtIds = partitions[me]->getDataSet()->GetCell(*icId)->GetPointIds();
1237  int numCellPts = cellPtIds->GetNumberOfIds();
1238  for (int i = 0; i < numCellPts; ++i) {
1239  int ptId = cellPtIds->GetId(i);
1240  if (ptId == *inId) {
1241  inSentCell = true;
1242  }
1243  }
1244  }
1245  if (inRmvCell && !inSentCell) {
1246  rmvNodeLst.push_back(*inId);
1247  }
1248  }
1249  // std::cout << " Number of false positive virtual volume nodes to remove "
1250  // << rmvNodeLst.size() << std::endl;
1251  for (auto inId = rmvNodeLst.begin(); inId != rmvNodeLst.end(); inId++) {
1252  // std::cout << "removing node: " << *inId << std::endl;
1253  sentNodes[me][you].erase(*inId);
1254  int globId = partToGlobNodeMap[me][*inId];
1255  this->receivedNodes[you][me].erase(globId);
1256  }
1257  }
1258 }
1259 
1260 vtkSmartPointer<vtkEdgeTable> RocPartCommGenRunner::createPartitionEdgeTable(
1261  int iPart) const {
1262  if (iPart > partitions.size()) {
1263  std::cerr << "Wrong partition number, there are " << partitions.size()
1264  << " partitions exisiting." << std::endl;
1265  throw;
1266  }
1267  vtkSmartPointer<vtkEdgeTable> eTab = vtkSmartPointer<vtkEdgeTable>::New();
1268  eTab->Initialize();
1269  eTab->Reset();
1270  eTab->InitEdgeInsertion(partitions[iPart]->getNumberOfPoints());
1271  // int test;
1272 
1273  // loop through all cells of the partition
1274  for (nemId_t ic = 0; ic < partitions[iPart]->getNumberOfCells(); ic++) {
1275  // traverse all edges of the cell
1276  // get all edges of the cells and make sure at least three are shared with
1277  // the current partition
1278  std::map<nemId_t, std::vector<double>> cellPntIdCrd =
1279  partitions[iPart]->getCell(ic);
1280 
1281  // only works for tets for now
1282  for (auto iid1 = cellPntIdCrd.begin(); iid1 != cellPntIdCrd.end(); iid1++)
1283  for (auto iid2 = std::next(iid1, 1); iid2 != cellPntIdCrd.end(); iid2++)
1284  /*test = */ eTab->InsertEdge(iid1->first, iid2->first);
1285  }
1286  return eTab;
1287 }
1288 
1289 void RocPartCommGenRunner::getSharedPatchInformation() {
1290  // get glob to part node maps for intersection calc
1291  std::map<int, std::map<int, std::map<int, int>>> patchProcGlobToPartNodeMaps;
1292  std::map<int, std::map<int, std::map<int, int>>> patchProcPartToGlobNodeMaps;
1293  std::map<int, std::map<int, std::vector<int>>> patchProcGlobNodeIdsMaps;
1294 
1295  for (int i = 0; i < this->sharedPatchNodes.size(); ++i) {
1296  auto it = this->patchesOfSurfacePartitions[i].begin();
1297  while (it != this->patchesOfSurfacePartitions[i].end()) {
1298  // get global ids of patch it->first on proc i (only if patch mesh exists)
1299  vtkSmartPointer<vtkDataArray> vtkGlobPatchNodeIds =
1300  it->second->getDataSet()->GetPointData()->GetArray("GlobalNodeIds");
1301  std::map<int, int> patchGlobToPartNodeMap;
1302  std::map<int, int> patchPartToGlobNodeMap;
1303  for (int j = 0; j < vtkGlobPatchNodeIds->GetNumberOfTuples(); ++j) {
1304  int globNodeId = static_cast<int>(vtkGlobPatchNodeIds->GetTuple1(j));
1305  patchGlobToPartNodeMap[globNodeId] = j;
1306  patchPartToGlobNodeMap[j] = globNodeId;
1307  }
1308  patchProcGlobToPartNodeMaps[it->first][i] = patchGlobToPartNodeMap;
1309  patchProcPartToGlobNodeMaps[it->first][i] = patchPartToGlobNodeMap;
1310  patchProcGlobNodeIdsMaps[it->first][i] =
1311  nemAux::getSortedKeys(patchGlobToPartNodeMap);
1312  ++it;
1313  }
1314  }
1315  for (int me = 0; me < this->surfacePartitions.size(); ++me) {
1316  auto it = this->patchesOfSurfacePartitions[me].begin();
1317  while (it != this->patchesOfSurfacePartitions[me].end()) {
1318  if (!(patchProcGlobNodeIdsMaps[it->first].find(me) ==
1319  patchProcGlobNodeIdsMaps[it->first].end())) {
1320  for (int you = 0; you < this->surfacePartitions.size(); ++you) {
1321  auto it1 = this->patchesOfSurfacePartitions[you].begin();
1322  while (it1 != this->patchesOfSurfacePartitions[you].end()) {
1323  if (!(patchProcGlobNodeIdsMaps[it1->first].find(you) ==
1324  patchProcGlobNodeIdsMaps[it1->first].end())) {
1325  if (!(you == me && it->first == it1->first)) {
1326  std::vector<int> tmpVec;
1327  std::set_intersection(
1328  patchProcGlobNodeIdsMaps[it->first][me].begin(),
1329  patchProcGlobNodeIdsMaps[it->first][me].end(),
1330  patchProcGlobNodeIdsMaps[it1->first][you].begin(),
1331  patchProcGlobNodeIdsMaps[it1->first][you].end(),
1332  std::back_inserter(tmpVec));
1333  if (tmpVec.size()) {
1334  this->sharedPatchNodes[me][it->first][you][it1->first].resize(
1335  tmpVec.size());
1336  this->sharedPatchNodes[you][it1->first][me][it->first].resize(
1337  tmpVec.size());
1338  for (int i = 0; i < tmpVec.size(); ++i) {
1339  int localPntId =
1340  patchProcGlobToPartNodeMaps[it->first][me][tmpVec[i]];
1341  this->sharedPatchNodes[me][it->first][you][it1->first][i] =
1342  localPntId;
1343  localPntId =
1344  patchProcGlobToPartNodeMaps[it1->first][you][tmpVec[i]];
1345  this->sharedPatchNodes[you][it1->first][me][it->first][i] =
1346  localPntId;
1347  }
1348  }
1349  }
1350  }
1351  ++it1;
1352  }
1353  }
1354  }
1355  ++it;
1356  }
1357  }
1358 }
1359 
1360 vtkSmartPointer<vtkPolyData> RocPartCommGenRunner::deleteInterPartitionSurface(
1361  std::shared_ptr<meshBase> fullSurf,
1362  vtkSmartPointer<vtkDataSet> _partSurf) const {
1363  vtkSmartPointer<vtkPolyData> partSurf = vtkPolyData::SafeDownCast(_partSurf);
1364 
1365  // build cell locator for full surface
1366  vtkSmartPointer<vtkStaticCellLocator> fullSurfCellLocator =
1367  fullSurf->buildStaticCellLocator();
1368 
1369  // build upward links from points to cells
1370  partSurf->BuildLinks();
1371 
1372  // allocate generic cell for FindCell calls
1373  vtkSmartPointer<vtkGenericCell> genCell =
1375  vtkSmartPointer<vtkGenericCell> genCell1 =
1377  vtkSmartPointer<vtkIdList> cellPointIds = vtkSmartPointer<vtkIdList>::New();
1378  std::unordered_set<int> cellsToDelete;
1379  std::unordered_set<int> pointsToDelete;
1380  int numToDelete = 0;
1381 
1382  for (int i = 0; i < partSurf->GetNumberOfCells(); ++i) {
1383  // get center of cell from part surf
1384  double center[3] = {0., 0., 0.};
1385  partSurf->GetCell(i, genCell);
1386  for (int j = 0; j < genCell->GetNumberOfPoints(); ++j) {
1387  double point[3];
1388  genCell->GetPoints()->GetPoint(j, point);
1389  for (int k = 0; k < 3; ++k) center[k] += point[k] / 3.;
1390  }
1391 
1392  // params to find center in full surf with locator
1393  double closestPoint[3];
1394  vtkIdType id;
1395  int subid;
1396  double minDist2;
1397 
1398  // look for point in full surf cells
1399  fullSurfCellLocator->FindClosestPoint(center, closestPoint, genCell, id,
1400  subid, minDist2);
1401  if (minDist2 > this->searchTolerance) {
1402  cellsToDelete.insert(i);
1403  partSurf->GetCellPoints(i, cellPointIds);
1404  for (int l = 0; l < cellPointIds->GetNumberOfIds(); ++l) {
1405  int pntId = static_cast<int>(cellPointIds->GetId(l));
1406  pointsToDelete.insert(pntId);
1407  }
1408  cellPointIds->Reset();
1409  numToDelete += 1;
1410  }
1411  }
1412  std::unordered_set<int>::iterator it = pointsToDelete.begin();
1413  while (it != pointsToDelete.end()) {
1414  partSurf->DeletePoint(*it);
1415  ++it;
1416  }
1417  it = cellsToDelete.begin();
1418  while (it != cellsToDelete.end()) {
1419  partSurf->DeleteCell(*it);
1420  ++it;
1421  }
1422  partSurf->RemoveDeletedCells();
1423 
1424  // force removal of cells, points and duplicates
1425  vtkSmartPointer<vtkCleanPolyData> cleanPolyData =
1427  cleanPolyData->SetInputData(partSurf);
1428  cleanPolyData->Update();
1429  return cleanPolyData->GetOutput();
1430 }
1431 
1432 void RocPartCommGenRunner::extractPatches() {
1433  // calculating patches of surface partitions
1434  this->patchesOfSurfacePartitions.resize(surfacePartitions.size());
1435  for (int i = 0; i < this->surfacePartitions.size(); ++i) {
1436  std::map<int, std::vector<nemId_t>> patchPartitionCellMap;
1437  vtkSmartPointer<vtkDataArray> patchNumbers =
1438  this->surfacePartitions[i]->getDataSet()->GetCellData()->GetArray(
1439  "patchNo");
1440  for (int j = 0; j < patchNumbers->GetNumberOfTuples(); ++j) {
1441  int patchNo = static_cast<int>(patchNumbers->GetTuple1(j));
1442  patchPartitionCellMap[patchNo].push_back(j);
1443  }
1444  auto it = patchPartitionCellMap.begin();
1445  while (it != patchPartitionCellMap.end()) {
1446  this->patchesOfSurfacePartitions[i][it->first] =
1448  this->surfacePartitions[i].get(), it->second));
1449  if (this->writeAllFiles > 0) {
1450  std::stringstream ss;
1451  ss << prefixPath + "extractedPatch" << it->first << "OfProc" << i
1452  << ".vtu";
1453  this->patchesOfSurfacePartitions[i][it->first]->write(ss.str());
1454  }
1455  ++it;
1456  }
1457  }
1458 
1459  // calculating virtual cells of the patches of surface partitions
1461  surfacePartitions.size());
1462  for (int i = 0; i < this->virtualCellsOfSurfPartitions.size(); ++i) {
1463  auto it = virtualCellsOfSurfPartitions[i].begin();
1464  while (it != virtualCellsOfSurfPartitions[i].end()) {
1465  std::map<int, std::vector<nemId_t>> virtualPatchPartitionCellMap;
1466  vtkSmartPointer<vtkDataArray> virtualPatchNumbers =
1467  it->second->getDataSet()->GetCellData()->GetArray("patchNo");
1468  for (int j = 0; j < virtualPatchNumbers->GetNumberOfTuples(); ++j) {
1469  int patchNo = static_cast<int>(virtualPatchNumbers->GetTuple1(j));
1470  virtualPatchPartitionCellMap[patchNo].push_back(j);
1471  }
1472  auto it1 = virtualPatchPartitionCellMap.begin();
1473  while (it1 != virtualPatchPartitionCellMap.end()) {
1474  this->virtualCellsOfPatchesOfSurfacePartitions[i][it->first]
1475  [it1->first] =
1477  meshBase::extractSelectedCells(it->second.get(), it1->second));
1478  if (this->writeAllFiles > 0) {
1479  std::stringstream ss;
1480  ss << prefixPath + "extractedVirtualPatch" << it1->first << "Of" << i
1481  << "FromProc" << it->first << ".vtu";
1482  this->virtualCellsOfPatchesOfSurfacePartitions[i][it->first]
1483  [it1->first]
1484  ->write(ss.str());
1485  }
1486  ++it1;
1487  }
1488  ++it;
1489  }
1490  }
1491 }
1492 
1493 RocPartCommGenRunner::~RocPartCommGenRunner() {
1494  std::cout << "RocPartCommGenRunner destroyed" << std::endl;
1495 }
1496 
1497 void RocPartCommGenRunner::writeSurfCgns(const std::string &prefix, int me) {
1498  // generating file name and instantiating a writer
1499  std::stringstream ss;
1500  ss << prefixPath << prefix << "_" << this->base_t
1501  << (me < 1000 ? (me < 100 ? (me < 10 ? "_000" : "_00") : "_0") : "_") << me
1502  << ".cgns";
1503  std::string cgFname(ss.str());
1504  std::unique_ptr<cgnsWriter> writer =
1505  std::unique_ptr<cgnsWriter>(new cgnsWriter(cgFname, prefix, 2, 3, 0));
1506 
1507  // initialize units, dimensions, and magnitude based on rocstar convention
1508  writer->setFluidUnitsMap();
1509  writer->setFluidDimMap();
1510  writer->setFluidMagMap();
1511  writer->setiFluidUnitsMap();
1512  writer->setiFluidDimMap();
1513  writer->setiFluidMagMap();
1514  writer->setBurnUnitsMap();
1515  writer->setBurnDimMap();
1516  writer->setBurnMagMap();
1517 
1518  // set time stamp
1519  writer->setTimestamp(this->trimmed_base_t);
1520 
1521  // define elementary information
1522  writer->setUnits(CGNS_ENUMV(Kilogram), CGNS_ENUMV(Meter), CGNS_ENUMV(Second),
1523  CGNS_ENUMV(Kelvin), CGNS_ENUMV(Degree));
1524 
1525  // baseitrname, nTstep, timeVal
1526  writer->setBaseItrData("TimeIterValues", 1, std::stod(this->trimmed_base_t));
1527 
1528  // write elementary grid information to file
1529  writer->writeGridToFile();
1530  std::string grdpntr("Grid");
1531  grdpntr += this->trimmed_base_t;
1532  std::string flowsolpntr("NodeData");
1533  flowsolpntr += this->trimmed_base_t;
1534  ss.str("");
1535  ss.clear();
1536  if (!(prefix == "burn" || prefix == "iburn_all")) {
1537  // set Win data
1538  std::string winName("WinData");
1539  winName += this->trimmed_base_t;
1540  writer->setIntData(winName, 1);
1541  writer->writeWinToFile();
1542  }
1543 
1544  // vtkIdList for mapping surface node indices to volume indices
1545  vtkSmartPointer<vtkIdList> result = vtkSmartPointer<vtkIdList>::New();
1546  vtkSmartPointer<vtkPointLocator> pointLocator =
1548  vtkSmartPointer<vtkPoints> myPoints = vtkSmartPointer<vtkPoints>::New();
1549  for (vtkIdType i = 0; i < procVolMesh[me]->getDataSet()->GetNumberOfPoints();
1550  i++)
1551  myPoints->InsertNextPoint(procVolMesh[me]->getDataSet()->GetPoint(i));
1552  vtkSmartPointer<vtkPolyData> myPointsData =
1554  myPointsData->SetPoints(myPoints);
1555  pointLocator->SetDataSet(myPointsData);
1556  pointLocator->AutomaticOn();
1557  pointLocator->BuildLocator();
1558 
1559  // begin loop over surface patches of this partition
1560  auto it = this->patchesOfSurfacePartitions[me].begin();
1561  int patchesFound = 0;
1562  int zone;
1563  while (it != this->patchesOfSurfacePartitions[me].end()) {
1564  if (prefix == this->getPatchType(it->first) ||
1565  ((prefix == "burn" || prefix == "iburn_all") &&
1566  (this->getPatchType(it->first) == "ifluid_b"))) {
1567  patchesFound += 1;
1568  int numVirtualCells = 0;
1569 
1570  // setting zone iter data
1571  writer->setZoneItrData("ZoneIterativeData", grdpntr, flowsolpntr);
1572  ss.str("");
1573  ss.clear();
1574  zone = this->surfZoneMap[me][it->first];
1575  ss << ((me + 1) >= 10 ? "" : "0") << me + 1 << (it->first < 10 ? "0" : "")
1576  << zone;
1577 
1578  // vector to hold real patch mesh and all virtuals from same patch on
1579  // other procs
1580  std::vector<std::shared_ptr<meshBase>>
1581  patchOfPartitionWithAllVirtualCells;
1582 
1583  // vector to hold real patch mesh
1584  std::vector<std::shared_ptr<meshBase>> patchOfPartition;
1585 
1586  // first push back real cells
1587  patchOfPartitionWithAllVirtualCells.push_back(it->second);
1588  patchOfPartition.push_back(it->second);
1589 
1590  // iterate over virtual cells of the partition's patch and push back
1591  auto virtItr = this->virtualCellsOfPatchesOfSurfacePartitions[me].begin();
1592  while (virtItr !=
1593  this->virtualCellsOfPatchesOfSurfacePartitions[me].end()) {
1594  auto virtItr1 = virtItr->second.begin();
1595  while (virtItr1 != virtItr->second.end()) {
1596  // if the patch is the same as the one on the other proc
1597  if (it->first == virtItr1->first)
1598  if (virtItr1->second->getNumberOfCells()) {
1599  // push back virtual cells from same patch on other proc
1600  patchOfPartitionWithAllVirtualCells.push_back(virtItr1->second);
1601  numVirtualCells += virtItr1->second->getNumberOfCells();
1602  }
1603  ++virtItr1;
1604  }
1605  ++virtItr;
1606  }
1607 
1608  // merge real cells for this partition
1609  std::shared_ptr<meshBase> patchOfPartitionWithRealMesh =
1610  meshBase::stitchMB(patchOfPartition);
1611 
1612  // merge virtual cells into real mesh for this partition
1613  std::shared_ptr<meshBase> patchOfPartitionWithVirtualMesh =
1614  meshBase::stitchMB(patchOfPartitionWithAllVirtualCells);
1615 
1616  // set the zone
1617  writer->setZone(ss.str(), CGNS_ENUMV(Unstructured));
1618 
1619  // all pconn stuff is shared nodes, so no ghost entities
1620  writer->setPconnGhostDescriptor(0);
1621 
1622  // set num real vertices
1623  writer->setNVrtx(it->second->getNumberOfPoints());
1624 
1625  // set num real cells for this patch of this partition
1626  writer->setNCell(it->second->getNumberOfCells());
1627 
1628  // define and set coordinates
1629  std::vector<std::vector<double>> coords;
1630 
1631  coords = patchOfPartitionWithVirtualMesh->getVertCrds();
1632 
1633  std::vector<nemId_t> cgConnReal_nemId_t(it->second->getConnectivities());
1634  // FIXME: Narrowing conversion from nemId_t to cgsize_t, which is int
1635  /// by default, long int if CGNS is built with 64-bit explicitly enabled
1636  std::vector<cgsize_t> cgConnReal(cgConnReal_nemId_t.begin(),
1637  cgConnReal_nemId_t.end());
1638  for (auto &tmpit : cgConnReal) tmpit += 1;
1639 
1640  // define virtual connectivities and 1-base indexing
1641  std::vector<nemId_t> cgConnVirtual_nemId_t(
1642  patchOfPartitionWithVirtualMesh->getConnectivities());
1643  // FIXME: Narrowing conversion from nemId_t to int.
1644  std::vector<cgsize_t> cgConnVirtual(cgConnVirtual_nemId_t.begin(),
1645  cgConnVirtual_nemId_t.end());
1646 
1647  cgConnVirtual.erase(cgConnVirtual.begin(),
1648  cgConnVirtual.begin() + cgConnReal.size());
1649  for (auto &tmpit : cgConnVirtual) tmpit += 1;
1650 
1651  // swap ordering of triangles
1652  // from counter-clockwise to clockwise convention
1653  this->swapTriOrdering(cgConnReal);
1654  this->swapTriOrdering(cgConnVirtual);
1655 
1656  // construct surface-to-volume mapping of vertex IDs
1657  // create vectors for t3g indices
1658  // map real vertices
1659  // construct map from local to global vertices and vice versa
1660  std::vector<int> cgConnRealGlobal1;
1661  std::vector<int> cgConnRealGlobal2;
1662  std::vector<int> cgConnRealGlobal3;
1663  std::vector<int> cgConnVirtualGlobal1;
1664  std::vector<int> cgConnVirtualGlobal2;
1665  std::vector<int> cgConnVirtualGlobal3;
1666  vtkIdType foundId;
1667  double pntCoor[3];
1668  std::map<int, int> loc2Glob;
1669  std::map<int, int> glob2Loc;
1670 
1671  // build up maps between local and global
1672  // get global real IDs
1673  for (auto itr = cgConnReal.begin(); itr != cgConnReal.end(); ++itr) {
1674  // connectivity information before reshuffling
1675  // undo 1-base indexing
1676  pntCoor[0] = coords[0][*itr - 1];
1677  pntCoor[1] = coords[1][*itr - 1];
1678  pntCoor[2] = coords[2][*itr - 1];
1679  foundId = pointLocator->FindClosestPoint(pntCoor);
1680 
1681  loc2Glob[*itr] = foundId + 1; // build up local-to-global map
1682  glob2Loc[foundId + 1] = *itr; // build up global-to-local map
1683 
1684  ++itr;
1685  pntCoor[0] = coords[0][*itr - 1];
1686  pntCoor[1] = coords[1][*itr - 1];
1687  pntCoor[2] = coords[2][*itr - 1];
1688  foundId = pointLocator->FindClosestPoint(pntCoor);
1689  loc2Glob[*itr] = foundId + 1;
1690  glob2Loc[foundId + 1] = *itr;
1691 
1692  ++itr;
1693  pntCoor[0] = coords[0][*itr - 1];
1694  pntCoor[1] = coords[1][*itr - 1];
1695  pntCoor[2] = coords[2][*itr - 1];
1696  foundId = pointLocator->FindClosestPoint(pntCoor);
1697  loc2Glob[*itr] = foundId + 1;
1698  glob2Loc[foundId + 1] = *itr;
1699  }
1700 
1701  // get global virtual IDs
1702  if (numVirtualCells) {
1703  for (auto itr = cgConnVirtual.begin(); itr != cgConnVirtual.end();
1704  ++itr) {
1705  pntCoor[0] = coords[0][*itr - 1];
1706  pntCoor[1] = coords[1][*itr - 1];
1707  pntCoor[2] = coords[2][*itr - 1];
1708  foundId = pointLocator->FindClosestPoint(pntCoor);
1709  if (loc2Glob.find(*itr) == loc2Glob.end()) {
1710  loc2Glob[*itr] = foundId + 1;
1711  glob2Loc[foundId + 1] = *itr;
1712  }
1713  ++itr;
1714 
1715  pntCoor[0] = coords[0][*itr - 1];
1716  pntCoor[1] = coords[1][*itr - 1];
1717  pntCoor[2] = coords[2][*itr - 1];
1718  foundId = pointLocator->FindClosestPoint(pntCoor);
1719  if (loc2Glob.find(*itr) == loc2Glob.end()) {
1720  loc2Glob[*itr] = foundId + 1;
1721  glob2Loc[foundId + 1] = *itr;
1722  }
1723  ++itr;
1724 
1725  pntCoor[0] = coords[0][*itr - 1];
1726  pntCoor[1] = coords[1][*itr - 1];
1727  pntCoor[2] = coords[2][*itr - 1];
1728  foundId = pointLocator->FindClosestPoint(pntCoor);
1729  if (loc2Glob.find(*itr) == loc2Glob.end()) {
1730  loc2Glob[*itr] = foundId + 1;
1731  glob2Loc[foundId + 1] = *itr;
1732  }
1733  }
1734  }
1735 
1736  // sort coordinates according to global index
1737  std::vector<std::vector<double>> coordsTmp;
1738  std::vector<double> coordsXTmp;
1739  std::vector<double> coordsYTmp;
1740  std::vector<double> coordsZTmp;
1741 
1742  // global and local ids
1743  int /*gId, */ lId;
1744  for (auto itr = glob2Loc.begin(); itr != glob2Loc.end(); ++itr) {
1745  // gId = itr->first;
1746  lId = itr->second;
1747  coordsXTmp.push_back(coords[0][lId - 1]);
1748  coordsYTmp.push_back(coords[1][lId - 1]);
1749  coordsZTmp.push_back(coords[2][lId - 1]);
1750  }
1751  coordsTmp.push_back(coordsXTmp);
1752  coordsTmp.push_back(coordsYTmp);
1753  coordsTmp.push_back(coordsZTmp);
1754 
1755  // Sort coordinates according to global ID, but order all reals first,
1756  // then virtuals: [real ordered by gId][virtual ordered by gId]
1757 
1758  // separate real from virtual coords
1759  std::vector<std::vector<double>> realCoords;
1760  std::vector<std::vector<double>> virtCoords;
1761 
1762  // copy real and virtual coords and re-organize
1763  std::vector<double> realCoordsX(
1764  coords[0].begin(),
1765  coords[0].begin() + it->second->getNumberOfPoints());
1766  std::vector<double> realCoordsY(
1767  coords[1].begin(),
1768  coords[1].begin() + it->second->getNumberOfPoints());
1769  std::vector<double> realCoordsZ(
1770  coords[2].begin(),
1771  coords[2].begin() + it->second->getNumberOfPoints());
1772  std::vector<double> virtCoordsX(
1773  coords[0].begin() + it->second->getNumberOfPoints(), coords[0].end());
1774  std::vector<double> virtCoordsY(
1775  coords[1].begin() + it->second->getNumberOfPoints(), coords[1].end());
1776  std::vector<double> virtCoordsZ(
1777  coords[2].begin() + it->second->getNumberOfPoints(), coords[2].end());
1778  realCoords.push_back(realCoordsX);
1779  realCoords.push_back(realCoordsY);
1780  realCoords.push_back(realCoordsZ);
1781  virtCoords.push_back(virtCoordsX);
1782  virtCoords.push_back(virtCoordsY);
1783  virtCoords.push_back(virtCoordsZ);
1784 
1785  // concatenate real and virtual coords
1786  std::vector<std::vector<double>> realVirtCoordsTmp;
1787  std::vector<double> realCoordsTmpX;
1788  std::vector<double> realCoordsTmpY;
1789  std::vector<double> realCoordsTmpZ;
1790  std::vector<double> virtCoordsTmpX;
1791  std::vector<double> virtCoordsTmpY;
1792  std::vector<double> virtCoordsTmpZ;
1793 
1794  // sort real and virtual coords
1795  for (int i = 0; i < coordsTmp[0].size(); i++) {
1796  for (int j = 0; j < realCoords[0].size(); j++) {
1797  if (coordsTmp[0][i] == realCoords[0][j] &&
1798  coordsTmp[1][i] == realCoords[1][j] &&
1799  coordsTmp[2][i] == realCoords[2][j]) {
1800  realCoordsTmpX.push_back(coordsTmp[0][i]);
1801  realCoordsTmpY.push_back(coordsTmp[1][i]);
1802  realCoordsTmpZ.push_back(coordsTmp[2][i]);
1803  }
1804  }
1805  for (int j = 0; j < virtCoords[0].size(); j++) {
1806  if (coordsTmp[0][i] == virtCoords[0][j] &&
1807  coordsTmp[1][i] == virtCoords[1][j] &&
1808  coordsTmp[2][i] == virtCoords[2][j]) {
1809  virtCoordsTmpX.push_back(coordsTmp[0][i]);
1810  virtCoordsTmpY.push_back(coordsTmp[1][i]);
1811  virtCoordsTmpZ.push_back(coordsTmp[2][i]);
1812  }
1813  }
1814  }
1815 
1816  // reconstruct real and virtual coords after sorting
1817  realCoordsTmpX.insert(realCoordsTmpX.end(), virtCoordsTmpX.begin(),
1818  virtCoordsTmpX.end());
1819  realVirtCoordsTmp.push_back(realCoordsTmpX);
1820  realCoordsTmpY.insert(realCoordsTmpY.end(), virtCoordsTmpY.begin(),
1821  virtCoordsTmpY.end());
1822  realVirtCoordsTmp.push_back(realCoordsTmpY);
1823  realCoordsTmpZ.insert(realCoordsTmpZ.end(), virtCoordsTmpZ.begin(),
1824  virtCoordsTmpZ.end());
1825  realVirtCoordsTmp.push_back(realCoordsTmpZ);
1826 
1827  // build up a new map between loc2glob using coords and the sorted
1828  // real/virtual coords above
1829  std::map<int, int> loc2GlobReal;
1830  std::map<int, int> glob2LocReal;
1831  std::map<int, int> loc2GlobVirt;
1832  std::map<int, int> glob2LocVirt;
1833  for (int i = 0; i < coords[0].size(); i++) {
1834  for (int j = 0; j < realVirtCoordsTmp[0].size(); j++) {
1835  if (coords[0][i] == realVirtCoordsTmp[0][j] &&
1836  coords[1][i] == realVirtCoordsTmp[1][j] &&
1837  coords[2][i] == realVirtCoordsTmp[2][j]) {
1838  if (j < it->second->getNumberOfPoints()) {
1839  glob2LocReal[loc2Glob[i + 1]] = j + 1;
1840  loc2GlobReal[j + 1] = loc2Glob[i + 1];
1841  } else {
1842  glob2LocVirt[loc2Glob[i + 1]] = j + 1;
1843  loc2GlobVirt[j + 1 - it->second->getNumberOfPoints()] =
1844  loc2Glob[i + 1];
1845  }
1846  }
1847  }
1848  }
1849 
1850  // set new coords
1851  coords = realVirtCoordsTmp;
1852 
1853  // sort cgConn structures according to new loc2Glob and glob2Loc maps
1854  // get global real IDs
1855  for (auto itr = cgConnReal.begin(); itr != cgConnReal.end(); ++itr) {
1856  cgConnRealGlobal1.push_back(
1857  loc2GlobReal[*itr]); // redo 1-base indexing
1858  ++itr;
1859  cgConnRealGlobal2.push_back(loc2GlobReal[*itr]);
1860  ++itr;
1861  cgConnRealGlobal3.push_back(loc2GlobReal[*itr]);
1862  }
1863 
1864  // get global virtual IDs
1865  if (numVirtualCells) {
1866  for (auto itr = cgConnVirtual.begin(); itr != cgConnVirtual.end();
1867  ++itr) {
1868  cgConnVirtualGlobal1.push_back(loc2GlobVirt[*itr]);
1869  ++itr;
1870  cgConnVirtualGlobal2.push_back(loc2GlobVirt[*itr]);
1871  ++itr;
1872  cgConnVirtualGlobal3.push_back(loc2GlobVirt[*itr]);
1873  }
1874  } else {
1875  cgConnVirtualGlobal1.push_back(0);
1876  cgConnVirtualGlobal2.push_back(0);
1877  cgConnVirtualGlobal3.push_back(0);
1878  }
1879 
1880  // build old2New maps using glob2Loc and loc2Glob
1881  // building maps between old and new local Ids
1882  // old : local index enumerated for the patch inside the process
1883  // new : index enumerated for the patch with all its virtual cells
1884  // in neighbouring processes
1885  std::map<int, int> old2New;
1886  std::map<int, int> new2Old;
1887 
1888  // sort local and global real connectivities
1889  std::vector<cgsize_t> cgConnRealTmp;
1890  std::vector<int> cgConnRealGlobal1Tmp;
1891  std::vector<int> cgConnRealGlobal2Tmp;
1892  std::vector<int> cgConnRealGlobal3Tmp;
1893  int oldLid;
1894  int newLid;
1895 
1896  // looping over real connectivity
1897  for (auto itr = cgConnReal.begin(); itr != cgConnReal.end(); ++itr) {
1898  oldLid = *itr;
1899  newLid = std::distance(glob2LocReal.begin(),
1900  glob2LocReal.find(loc2Glob[*itr])) +
1901  1;
1902  old2New[oldLid] = newLid;
1903  new2Old[newLid] = oldLid;
1904  cgConnRealTmp.push_back(newLid);
1905  cgConnRealGlobal1Tmp.push_back(loc2Glob[oldLid]);
1906  ++itr;
1907 
1908  oldLid = *itr;
1909  newLid = std::distance(glob2LocReal.begin(),
1910  glob2LocReal.find(loc2Glob[*itr])) +
1911  1;
1912  old2New[oldLid] = newLid;
1913  new2Old[newLid] = oldLid;
1914  cgConnRealTmp.push_back(newLid);
1915  cgConnRealGlobal2Tmp.push_back(loc2Glob[oldLid]);
1916  ++itr;
1917 
1918  oldLid = *itr;
1919  newLid = std::distance(glob2LocReal.begin(),
1920  glob2LocReal.find(loc2Glob[*itr])) +
1921  1;
1922  old2New[oldLid] = newLid;
1923  new2Old[newLid] = oldLid;
1924  cgConnRealTmp.push_back(newLid);
1925  cgConnRealGlobal3Tmp.push_back(loc2Glob[oldLid]);
1926  }
1927 
1928  // sort local and global virtual connectivities
1929  std::vector<cgsize_t> cgConnVirtualTmp;
1930  std::vector<int> cgConnVirtualGlobal1Tmp;
1931  std::vector<int> cgConnVirtualGlobal2Tmp;
1932  std::vector<int> cgConnVirtualGlobal3Tmp;
1933  // int oldGid;
1934  // int newGid;
1935 
1936  if (numVirtualCells) {
1937  // looping over virtual connectivity
1938  for (auto itr = cgConnVirtual.begin(); itr != cgConnVirtual.end();
1939  ++itr) {
1940  oldLid = *itr;
1941  if (glob2LocVirt.find(loc2Glob[*itr]) != glob2LocVirt.end()) {
1942  newLid = std::distance(glob2LocVirt.begin(),
1943  glob2LocVirt.find(loc2Glob[*itr])) +
1944  1 + it->second->getNumberOfPoints();
1945  } else {
1946  newLid = std::distance(glob2LocReal.begin(),
1947  glob2LocReal.find(loc2Glob[*itr])) +
1948  1;
1949  }
1950  old2New[oldLid] = newLid;
1951  new2Old[newLid] = oldLid;
1952  cgConnVirtualTmp.push_back(newLid);
1953  cgConnVirtualGlobal1Tmp.push_back(loc2Glob[oldLid]);
1954  ++itr;
1955 
1956  oldLid = *itr;
1957  if (glob2LocVirt.find(loc2Glob[*itr]) != glob2LocVirt.end()) {
1958  newLid = std::distance(glob2LocVirt.begin(),
1959  glob2LocVirt.find(loc2Glob[*itr])) +
1960  1 + it->second->getNumberOfPoints();
1961  } else {
1962  newLid = std::distance(glob2LocReal.begin(),
1963  glob2LocReal.find(loc2Glob[*itr])) +
1964  1;
1965  }
1966  old2New[oldLid] = newLid;
1967  new2Old[newLid] = oldLid;
1968  cgConnVirtualTmp.push_back(newLid);
1969  cgConnVirtualGlobal2Tmp.push_back(loc2Glob[oldLid]);
1970  ++itr;
1971 
1972  oldLid = *itr;
1973  if (glob2LocVirt.find(loc2Glob[*itr]) != glob2LocVirt.end()) {
1974  newLid = std::distance(glob2LocVirt.begin(),
1975  glob2LocVirt.find(loc2Glob[*itr])) +
1976  1 + it->second->getNumberOfPoints();
1977  } else {
1978  newLid = std::distance(glob2LocReal.begin(),
1979  glob2LocReal.find(loc2Glob[*itr])) +
1980  1;
1981  }
1982  old2New[oldLid] = newLid;
1983  new2Old[newLid] = oldLid;
1984  cgConnVirtualTmp.push_back(newLid);
1985  cgConnVirtualGlobal3Tmp.push_back(loc2Glob[oldLid]);
1986  }
1987  }
1988 
1989  // assign re-ordered real connectivity
1990  cgConnReal = cgConnRealTmp;
1991 
1992  // assign re-ordered global real connectivity
1993  cgConnRealGlobal1 = cgConnRealGlobal1Tmp;
1994  cgConnRealGlobal2 = cgConnRealGlobal2Tmp;
1995  cgConnRealGlobal3 = cgConnRealGlobal3Tmp;
1996 
1997  // assign virtual connectivities
1998  if (numVirtualCells) {
1999  cgConnVirtual = cgConnVirtualTmp;
2000  cgConnVirtualGlobal1 = cgConnVirtualGlobal1Tmp;
2001  cgConnVirtualGlobal2 = cgConnVirtualGlobal2Tmp;
2002  cgConnVirtualGlobal3 = cgConnVirtualGlobal3Tmp;
2003  }
2004 
2005  if (!(prefix == "burn" || prefix == "iburn_all")) {
2006  // set num virtual vertices for this partition
2007  writer->setCoordRind(
2008  patchOfPartitionWithVirtualMesh->getNumberOfPoints() -
2009  it->second->getNumberOfPoints());
2010 
2011  // set number of real vertices in zone:
2012  writer->setNVrtx(it->second->getNumberOfPoints());
2013 
2014  // set grid coordinates
2015  writer->setGridXYZ(coords[0], coords[1], coords[2]);
2016  } else {
2017  coords[0].resize(it->second->getNumberOfPoints());
2018  coords[1].resize(it->second->getNumberOfPoints());
2019  coords[2].resize(it->second->getNumberOfPoints());
2020 
2021  // set grid coordinates
2022  writer->setGridXYZ(coords[0], coords[1], coords[2]);
2023 
2024  // set number of real vertices in zone:
2025  writer->setNVrtx(it->second->getNumberOfPoints());
2026  }
2027 
2028  writer->setSection(":t3:real", CGNS_ENUMV(TRI_3), cgConnReal);
2029 
2030  // for writing to rocflu vol/surf files (non-rocburn)
2031  if (!(prefix == "burn" || prefix == "iburn_all")) {
2032  // get pane data that is stored in element data (patchNo , bcflag,
2033  // cnstr_type)
2034  vtkSmartPointer<vtkDataArray> patchNos =
2035  patchOfPartitionWithRealMesh->getDataSet()->GetCellData()->GetArray(
2036  "patchNo");
2037  double patchNo[1];
2038  patchNos->GetTuple(0, patchNo);
2039 
2040  // write real and virtual patch information to Rocstar dimension file
2041  this->dimSurfWriter(me + 1, cgConnReal, cgConnVirtual,
2042  static_cast<int>(patchNo[0]));
2043 
2044  vtkSmartPointer<vtkDataArray> bcflags =
2045  patchOfPartitionWithRealMesh->getDataSet()->GetCellData()->GetArray(
2046  "bcflag");
2047  double bcflag[1];
2048  bcflags->GetTuple(0, bcflag);
2049 
2050  vtkSmartPointer<vtkDataArray> cnstr_types =
2051  patchOfPartitionWithRealMesh->getDataSet()->GetCellData()->GetArray(
2052  "cnstr_type");
2053  double cnstr_type[1];
2054  cnstr_types->GetTuple(0, cnstr_type);
2055 
2056  if (numVirtualCells) {
2057  writer->setNCell(numVirtualCells);
2058  writer->setSection(":t3:virtual", CGNS_ENUMV(TRI_3), cgConnVirtual);
2059  writer->setVirtElmRind(numVirtualCells);
2060  } else {
2061  writer->setVirtElmRind(0);
2062  }
2063 
2064  // Before writing Pconn vector, restructure format of vector
2065  int nGhost = 0;
2066  this->restructurePconn(this->surfPconns[me][it->first], me, 1, old2New,
2067  nGhost);
2068  writer->setPconnVec(this->surfPconns[me][it->first]);
2069  writer->setPconnLimits(this->pconnProcMin[me], this->pconnProcMax[me]);
2070 
2071  // Note: only tri elements supported
2072  writer->setGlobalSection("t3g:real#1of3", CGNS_ENUMV(TRI_3),
2073  cgConnRealGlobal1);
2074  writer->setGlobalNCell(cgConnRealGlobal1.size());
2075  writer->setGlobalSection("t3g:real#2of3", CGNS_ENUMV(TRI_3),
2076  cgConnRealGlobal2);
2077  writer->setGlobalNCell(cgConnRealGlobal2.size());
2078  writer->setGlobalSection("t3g:real#3of3", CGNS_ENUMV(TRI_3),
2079  cgConnRealGlobal3);
2080  writer->setGlobalNCell(cgConnRealGlobal3.size());
2081  writer->setGlobalSection("t3g:virtual#1of3", CGNS_ENUMV(TRI_3),
2082  cgConnVirtualGlobal1);
2083  writer->setGlobalNCell(cgConnVirtualGlobal1.size());
2084  writer->setGlobalSection("t3g:virtual#2of3", CGNS_ENUMV(TRI_3),
2085  cgConnVirtualGlobal2);
2086  writer->setGlobalNCell(cgConnVirtualGlobal2.size());
2087  writer->setGlobalSection("t3g:virtual#3of3", CGNS_ENUMV(TRI_3),
2088  cgConnVirtualGlobal3);
2089  writer->setGlobalNCell(cgConnVirtualGlobal3.size());
2090 
2091  // Set quad elements to be empty
2092  writer->setGlobalSection("q4g:real#1of4", CGNS_ENUMV(TETRA_4));
2093  writer->setGlobalNCell(0);
2094  writer->setGlobalSection("q4g:real#2of4", CGNS_ENUMV(TETRA_4));
2095  writer->setGlobalNCell(0);
2096  writer->setGlobalSection("q4g:real#3of4", CGNS_ENUMV(TETRA_4));
2097  writer->setGlobalNCell(0);
2098  writer->setGlobalSection("q4g:real#4of4", CGNS_ENUMV(TETRA_4));
2099  writer->setGlobalNCell(0);
2100  writer->setGlobalSection("q4g:virtual#1of4", CGNS_ENUMV(TETRA_4));
2101  writer->setGlobalNCell(0);
2102  writer->setGlobalSection("q4g:virtual#2of4", CGNS_ENUMV(TETRA_4));
2103  writer->setGlobalNCell(0);
2104  writer->setGlobalSection("q4g:virtual#3of4", CGNS_ENUMV(TETRA_4));
2105  writer->setGlobalNCell(0);
2106  writer->setGlobalSection("q4g:virtual#4of4", CGNS_ENUMV(TETRA_4));
2107  writer->setGlobalNCell(0);
2108 
2109  writer->setPatchNo((int)patchNo[0]);
2110  writer->setBcflag((int)bcflag[0]);
2111  writer->setCnstrtype((int)cnstr_type[0]);
2112  } else {
2113  writer->setNCell(1);
2114  writer->setSection("Empty:t3:virtual", CGNS_ENUMV(TRI_3),
2115  cgConnVirtual);
2116  writer->setVirtElmRind(numVirtualCells);
2117  }
2118 
2119  // Subtract surface faces off of volume faces total
2120  if (!(prefix == "burn" || prefix == "iburn_all"))
2121  this->nUniqueVolFaces[me] -=
2122  patchOfPartitionWithVirtualMesh->getDataSet()->GetNumberOfCells();
2123 
2124  // Set cgns writer types and zones
2125  if (!(prefix == "burn" || prefix == "iburn_all")) {
2126  // rocflu surface
2127  writer->setTypeFlag(1);
2128  writer->writeZoneToFile();
2129  } else {
2130  // rocburn surface
2131  writer->setTypeFlag(2);
2132  writer->writeZoneToFile();
2133  }
2134 
2135  // write solution data
2136  if (this->surfWithSol) {
2137  // transfer data to the surf-partition-with-virtual-cells mesh
2138  /*
2139  this->burnSurfWithSol->transfer(patchOfPartitionWithRealMesh.get(),
2140  "Consistent Interpolation");
2141  */
2142 
2143  std::shared_ptr<TransferBase> transfer;
2144 
2146  this->burnSurfWithSol.get(), patchOfPartitionWithRealMesh.get(),
2147  "Consistent Interpolation");
2148  transfer->run(this->burnSurfWithSol->getNewArrayNames());
2149 
2150  if (this->writeAllFiles > 1)
2151  patchOfPartitionWithRealMesh.get()->write(
2152  prefixPath + "_" + std::to_string(me) + "_real_patch_" +
2153  std::to_string(it->first) + ".vtu");
2154 
2155  // transfer data to the surf-partition-with-virtual-cells mesh
2156  /*
2157  this->surfWithSol->transfer(patchOfPartitionWithVirtualMesh.get(),
2158  "Consistent Interpolation");
2159  */
2160 
2162  this->surfWithSol.get(), patchOfPartitionWithVirtualMesh.get(),
2163  "Consistent Interpolation");
2164  transfer->run(this->surfWithSol->getNewArrayNames());
2165 
2166  if (this->writeAllFiles > 1)
2167  patchOfPartitionWithVirtualMesh.get()->write(
2168  prefixPath + "_" + std::to_string(me) + "_virtual_patch_" +
2169  std::to_string(it->first) + ".vtu");
2170 
2171  int numPointDataArr = this->surfWithSol->getDataSet()
2172  ->GetPointData()
2173  ->GetNumberOfArrays();
2174 
2175  // point data
2176  if (numPointDataArr) {
2177  std::string nodeName("NodeData");
2178  nodeName += this->trimmed_base_t;
2179  if (!(prefix == "burn" || prefix == "iburn_all")) {
2180  writer->setTypeFlag(1);
2181  writer->writeSolutionNode(nodeName, CGNS_ENUMV(Vertex), 0, 1);
2182  for (int i = 0; i < numPointDataArr; ++i) {
2183  std::vector<double> pointData;
2184  std::string dataName(
2185  this->surfWithSol->getDataSet()->GetPointData()->GetArrayName(
2186  i));
2187  patchOfPartitionWithVirtualMesh->getPointDataArray(dataName,
2188  pointData);
2189  writer->setTypeFlag(1);
2190 
2191  // map point data from old coordinates to new coordinates
2192  this->mapOld2NewPointData(pointData, new2Old);
2193  // write point data to file
2194  writer->writeSolutionField(
2195  dataName, nodeName, CGNS_ENUMV(RealDouble), &pointData[0u]);
2196  }
2197  } else {
2198  writer->setTypeFlag(1);
2199  writer->writeSolutionNode(nodeName, CGNS_ENUMV(Vertex), 1, 1);
2200  }
2201  }
2202 
2203  // cell data
2204  int numCellDataArr;
2205  if (prefix == "burn" || prefix == "iburn_all")
2206  numCellDataArr = this->burnSurfWithSol->getDataSet()
2207  ->GetCellData()
2208  ->GetNumberOfArrays();
2209  else
2210  numCellDataArr = this->surfWithSol->getDataSet()
2211  ->GetCellData()
2212  ->GetNumberOfArrays();
2213 
2214  // registering to writer
2215  if (numCellDataArr) {
2216  if (prefix != "burn") {
2217  std::string nodeName("ElemData");
2218  nodeName += this->trimmed_base_t;
2219  if (!(prefix == "burn" || prefix == "iburn_all")) {
2220  writer->setTypeFlag(1);
2221  writer->writeSolutionNode(nodeName, CGNS_ENUMV(CellCenter), 0, 1);
2222  } else if (prefix == "iburn_all") {
2223  writer->setTypeFlag(2);
2224  writer->writeSolutionNode(nodeName, CGNS_ENUMV(CellCenter), 0, 0);
2225  }
2226  // now loop through all cell data attributes
2227  for (int i = 0; i < numCellDataArr; ++i) {
2228  std::vector<double> cellData;
2229  std::string dataName;
2230  if (!(prefix == "burn" || prefix == "iburn_all")) {
2231  dataName = this->surfWithSol->getDataSet()
2232  ->GetCellData()
2233  ->GetArrayName(i);
2234  patchOfPartitionWithVirtualMesh->getCellDataArray(dataName,
2235  cellData);
2236  } else if (prefix == "iburn_all") {
2237  dataName = this->burnSurfWithSol->getDataSet()
2238  ->GetCellData()
2239  ->GetArrayName(i);
2240  patchOfPartitionWithRealMesh->getCellDataArray(dataName,
2241  cellData);
2242  }
2243 
2244  if (dataName != "bcflag" && dataName != "patchNo" &&
2245  dataName != "cnstr_type") {
2246  // Zero out grid speed for re-meshing
2247  if (dataName == "gs")
2248  for (double &itr : cellData) itr = 0;
2249 
2250  // If writing out cell centers, recompute them after re-meshing
2251  if (dataName == "centersX" || dataName == "centersY" ||
2252  dataName == "centersZ") {
2253  int ind;
2254  if (dataName == "centersX")
2255  ind = 0;
2256  else if (dataName == "centersY")
2257  ind = 1;
2258  else if (dataName == "centersZ")
2259  ind = 2;
2260 
2261  // Get total number of real nodes
2262  int nCells = cgConnReal.size() / 3;
2263  for (int i = 0; i < nCells; i++)
2264  cellData.push_back((coords[ind][cgConnReal[3 * i]] +
2265  coords[ind][cgConnReal[3 * i + 1]] +
2266  coords[ind][cgConnReal[3 * i + 2]]) /
2267  3);
2268  }
2269 
2270  // set num real cells for this patch of this partition
2271  if (prefix == "ifluid_ni" || prefix == "ifluid_b" ||
2272  prefix == "ifluid_nb") {
2273  writer->setTypeFlag(1);
2274  if (dataName == "bflag") {
2275  std::vector<int> bflag(cellData.begin(), cellData.end());
2276  writer->writeSolutionField(dataName, nodeName,
2277  CGNS_ENUMV(Integer), &bflag[0u]);
2278  } else {
2279  // write cell data to file
2280  writer->writeSolutionField(dataName, nodeName,
2281  CGNS_ENUMV(RealDouble),
2282  &cellData[0u]);
2283  }
2284  } else if (prefix == "burn" || prefix == "iburn_all") {
2285  writer->setTypeFlag(2);
2286  if (dataName == "bflag") {
2287  std::vector<int> cellDataInt(cellData.begin(),
2288  cellData.end());
2289 
2290  // write cell data to file
2291  writer->writeSolutionField(dataName, nodeName,
2292  CGNS_ENUMV(Integer),
2293  &cellDataInt[0u]);
2294  } else {
2295  // write cell data to file
2296  writer->writeSolutionField(dataName, nodeName,
2297  CGNS_ENUMV(RealDouble),
2298  &cellData[0u]);
2299  }
2300  }
2301  }
2302  }
2303  }
2304  }
2305  }
2306 
2307  // reset the section info
2308  writer->resetSections();
2309  writer->resetGlobalSections();
2310  }
2311  ++it;
2312  }
2313  if (patchesFound == 0) {
2314  writer->deleteFile();
2315  }
2316 }
2317 
2318 void RocPartCommGenRunner::writeVolCgns(const std::string &prefix, int proc,
2319  int type) {
2320  std::stringstream ss;
2321  ss << prefixPath << prefix << "_" << this->base_t
2322  << (proc < 1000 ? (proc < 100 ? (proc < 10 ? "_000" : "_00") : "_0") : "_")
2323  << proc << ".cgns";
2324  std::string cgFname(ss.str());
2325  std::unique_ptr<cgnsWriter> writer =
2326  std::unique_ptr<cgnsWriter>(new cgnsWriter(cgFname, "fluid", 3, 3, 0));
2327 
2328  // initialize Rocstar units, dimensions, and magnitude writing
2329  writer->setFluidUnitsMap();
2330  writer->setFluidDimMap();
2331  writer->setFluidMagMap();
2332  writer->setiFluidUnitsMap();
2333  writer->setiFluidDimMap();
2334  writer->setiFluidMagMap();
2335  writer->setBurnUnitsMap();
2336  writer->setBurnDimMap();
2337  writer->setBurnMagMap();
2338 
2339  // set time stamp
2340  writer->setTimestamp(this->trimmed_base_t);
2341 
2342  // define elementary information
2343  writer->setUnits(CGNS_ENUMV(Kilogram), CGNS_ENUMV(Meter), CGNS_ENUMV(Second),
2344  CGNS_ENUMV(Kelvin), CGNS_ENUMV(Degree));
2345 
2346  // baseitrname, nTstep, timeVal
2347  writer->setBaseItrData("TimeIterValues", 1, std::stod(this->trimmed_base_t));
2348 
2349  // setting zone iter data
2350  std::string gridpntr("Grid");
2351  gridpntr += this->trimmed_base_t;
2352  std::string flowsolpntr("NodeData");
2353  flowsolpntr += this->trimmed_base_t;
2354  writer->setZoneItrData("ZoneIterativeData", gridpntr, flowsolpntr);
2355  ss.str("");
2356  ss.clear();
2357  ss << ((proc + 1) >= 10 ? "" : "0") << proc + 1 << (type < 10 ? "0" : "")
2358  << type;
2359  volZoneMap.push_back(std::stoi(ss.str()));
2360 
2361  // vector to hold all virtual meshes and the partition's mesh for merging
2362  std::vector<std::shared_ptr<meshBase>> partitionWithAllVirtualCells;
2363  partitionWithAllVirtualCells.push_back(this->partitions[proc]);
2364 
2365  // iterate over vitual meshes to merge them and get number of virtual coords
2366  auto virtItr = this->virtualCellsOfPartitions[proc].begin();
2367  int numVirtualCells = 0;
2368  while (virtItr != this->virtualCellsOfPartitions[proc].end()) {
2369  // push virtual mesh into real
2370  partitionWithAllVirtualCells.push_back(virtItr->second);
2371  numVirtualCells += virtItr->second->getNumberOfCells();
2372  ++virtItr;
2373  }
2374 
2375  // merge virtual cells into real mesh for this partition
2376  std::shared_ptr<meshBase> partitionWithVirtualMesh =
2377  meshBase::stitchMB(partitionWithAllVirtualCells);
2378 
2379  // define coordinates
2380  std::vector<std::vector<double>> coords(
2381  partitionWithVirtualMesh->getVertCrds());
2382 
2383  // Save vertex coordinates for mapping between volume and surface
2384  this->procVolMesh.push_back(partitionWithVirtualMesh);
2385 
2386  // set the zone
2387  writer->setZone(ss.str(), CGNS_ENUMV(Unstructured));
2388 
2389  // set num real vertices for this partition
2390  writer->setNVrtx(partitions[proc]->getNumberOfPoints());
2391 
2392  // set num real cells for this partition
2393  writer->setNCell(partitions[proc]->getNumberOfCells());
2394 
2395  // set grid coordinates
2396  writer->setGridXYZ(coords[0], coords[1], coords[2]);
2397 
2398  // set num virtual vertices for this partition
2399  writer->setCoordRind(partitionWithVirtualMesh->getNumberOfPoints() -
2400  partitions[proc]->getNumberOfPoints());
2401 
2402  // define real connectivities and 1-base indexing
2403  std::vector<nemId_t> cgConnReal_nemId_t(
2404  partitions[proc]->getConnectivities());
2405  // FIXME: Narrowing conversion from nemId_t to int.
2406  std::vector<cgsize_t> cgConnReal(cgConnReal_nemId_t.begin(),
2407  cgConnReal_nemId_t.end());
2408  for (auto &it : cgConnReal) it += 1;
2409 
2410  // define virtual connectivities and 1-base indexing
2411  std::vector<nemId_t> cgConnVirtual_nemId_t(
2412  partitionWithVirtualMesh->getConnectivities());
2413  // FIXME: Narrowing conversion from nemId_t to int.
2414  std::vector<cgsize_t> cgConnVirtual(cgConnVirtual_nemId_t.begin(),
2415  cgConnVirtual_nemId_t.end());
2416 
2417  cgConnVirtual.erase(cgConnVirtual.begin(),
2418  cgConnVirtual.begin() + cgConnReal.size());
2419  for (auto &it : cgConnVirtual) it += 1;
2420 
2421  writer->setSection(":T4:real", CGNS_ENUMV(TETRA_4), cgConnReal);
2422  writer->setNCell(numVirtualCells);
2423  writer->setSection(":T4:virtual", CGNS_ENUMV(TETRA_4), cgConnVirtual);
2424  writer->setVirtElmRind(numVirtualCells);
2425 
2426  // Before writing Pconn vector, restructure format of vector
2427  int nGhost = 0;
2428  std::map<int, int> tmp{};
2429  this->restructurePconn(volPconns[proc], proc, 0, tmp, nGhost);
2430 
2431  // get number of ghost entities in pconn vec
2432  int ghostDescriptor = nGhost;
2433 
2434  // register this with writer
2435  writer->setPconnGhostDescriptor(ghostDescriptor);
2436 
2437  // set volume pconn vector
2438  writer->setPconnVec(this->volPconns[proc]);
2439  writer->setPconnLimits(this->pconnProcMin[proc], this->pconnProcMax[proc]);
2440 
2441  writer->setNCell(numVirtualCells);
2442 
2443  // write some modin files
2444  this->dimWriter(proc + 1, this->partitions[proc], partitionWithVirtualMesh);
2445  this->clearBorderVector();
2446  this->cmpWriter(proc + 1,
2447  partitionWithVirtualMesh->getDataSet()->GetNumberOfCells());
2448 
2449  // Get number of unique faces in the volume mesh
2450  std::vector<std::vector<int>> allFaces;
2451  std::vector<int> idList;
2452  for (int iCell = 0;
2453  iCell < partitionWithVirtualMesh->getDataSet()->GetNumberOfCells();
2454  iCell++) {
2455  auto myCell = partitionWithVirtualMesh->getDataSet()->GetCell(iCell);
2456  for (int iFace = 0; iFace < myCell->GetNumberOfFaces(); iFace++) {
2457  auto myFace = myCell->GetFace(iFace);
2458  idList.clear();
2459  auto ptIds = myFace->GetPointIds();
2460  for (int iPt = 0; iPt < myFace->GetNumberOfPoints(); iPt++)
2461  idList.push_back(ptIds->GetId(iPt));
2462  std::sort(idList.begin(), idList.end());
2463  allFaces.push_back(idList);
2464  }
2465  }
2466  std::sort(allFaces.begin(), allFaces.end());
2467  allFaces.erase(std::unique(allFaces.begin(), allFaces.end()), allFaces.end());
2468  this->nUniqueVolFaces[proc] = allFaces.size();
2469 
2470  // set number of unique volume faces
2471  writer->setVolCellFacesNumber(this->nUniqueVolFaces[proc]);
2472 
2473  // write volume grid
2474  writer->writeGridToFile();
2475  writer->setTypeFlag(0);
2476  writer->writeZoneToFile();
2477 
2478  // write solution da
2479  if (this->volWithSol) {
2480  // transfer data to the partition-with-virtual-cells mesh
2481  this->volWithSol->setContBool(this->smoothC2CTrans);
2482 
2483  /*
2484  this->volWithSol->transfer(partitionWithVirtualMesh.get(),
2485  "Consistent Interpolation");
2486  */
2487  auto transfer = TransferDriver::CreateTransferObject(
2488  this->volWithSol.get(), partitionWithVirtualMesh.get(),
2489  "Consistent Interpolation");
2490  transfer->run(this->volWithSol->getNewArrayNames());
2491 
2492  // output volumetric information if needed
2493  if (this->writeAllFiles > 1)
2494  partitionWithVirtualMesh.get()->write(prefixPath + "_vol_part_" +
2495  std::to_string(proc) + ".vtu");
2496 
2497  int numPointDataArr =
2498  this->volWithSol->getDataSet()->GetPointData()->GetNumberOfArrays();
2499  if (numPointDataArr) {
2500  std::string nodeName("NodeData");
2501  nodeName += this->trimmed_base_t;
2502  writer->setTypeFlag(1);
2503  writer->writeSolutionNode(nodeName, CGNS_ENUMV(Vertex), 0, 1);
2504 
2505  // begin with point data
2506  for (int i = 0; i < numPointDataArr; ++i) {
2507  std::vector<double> pointData;
2508  partitionWithVirtualMesh->getPointDataArray(i, pointData);
2509  std::string dataName(
2510  this->volWithSol->getDataSet()->GetPointData()->GetArrayName(i));
2511  writer->setTypeFlag(0);
2512  writer->writeSolutionField(dataName, nodeName, CGNS_ENUMV(RealDouble),
2513  &pointData[0u]);
2514  }
2515  }
2516  int numCellDataArr =
2517  this->volWithSol->getDataSet()->GetCellData()->GetNumberOfArrays();
2518  if (numCellDataArr) {
2519  std::string nodeName("ElemData");
2520  nodeName += this->trimmed_base_t;
2521  writer->setTypeFlag(1);
2522  writer->writeSolutionNode(nodeName, CGNS_ENUMV(CellCenter), 0, 1);
2523 
2524  // now do cell data
2525  for (int i = 0; i < numCellDataArr; ++i) {
2526  std::vector<double> cellData;
2527  partitionWithVirtualMesh->getCellDataArray(i, cellData);
2528  std::string dataName(
2529  this->volWithSol->getDataSet()->GetCellData()->GetArrayName(i));
2530  writer->setTypeFlag(0);
2531  writer->writeSolutionField(dataName, nodeName, CGNS_ENUMV(RealDouble),
2532  &cellData[0u]);
2533  }
2534  }
2535  }
2536 }
2537 
2538 void RocPartCommGenRunner::writeVolCellFaces(const std::string &prefix,
2539  int proc, int type) const {
2540  std::stringstream ss;
2541  ss << prefixPath << prefix << "_" << this->base_t
2542  << (proc < 1000 ? (proc < 100 ? (proc < 10 ? "_000" : "_00") : "_0") : "_")
2543  << proc << ".cgns";
2544  std::string cgFname(ss.str());
2545  std::unique_ptr<cgnsWriter> writer =
2546  std::unique_ptr<cgnsWriter>(new cgnsWriter(cgFname, "fluid", 3, 3, 1));
2547 
2548  // initialize Rocstar units, dimensions, and magnitude writing
2549  writer->setFluidDimMap();
2550  writer->setFluidUnitsMap();
2551  writer->setFluidMagMap();
2552 
2553  // set time stamp
2554  writer->setTimestamp(this->trimmed_base_t);
2555 
2556  // baseitrname, nTstep, timeVal
2557  writer->setBaseItrData("TimeIterValues", 1, std::stod(this->trimmed_base_t));
2558 
2559  // write number of interior volume faces to already written volume files
2560  // used for grid speed (gs)
2561  writer->setVolCellFacesNumber(this->nUniqueVolFaces.at(proc));
2562  writer->writeVolCellFacesNumber();
2563 }
2564 
2565 void RocPartCommGenRunner::mapOld2NewPointData(
2566  std::vector<double> &nodeData, const std::map<int, int> &new2Old) const {
2567  std::vector<double> nodeDataTmp;
2568  for (auto itr = new2Old.begin(); itr != new2Old.end(); ++itr) {
2569  nodeDataTmp.push_back(nodeData[itr->second - 1]);
2570  }
2571  nodeData = nodeDataTmp;
2572 }
2573 
2574 void RocPartCommGenRunner::restructurePconn(std::vector<int> &pConnVec,
2575  int proc, int volOrSurf,
2576  const std::map<int, int> &old2New,
2577  int &nGhost) {
2578  // Vectors to store each block for each zone
2579  //<zone, <block, <indices>>
2580  std::map<int, std::vector<std::vector<int>>> zoneToBlocks;
2581 
2582  // Temporary storage data structures
2583  std::vector<int> idTmp;
2584 
2585  // Get maximum of PconnVec (maximum of shared nodes)
2586  int zoneCount = 0;
2587  int idCount = -1;
2588  int currZone = -1;
2589  int max = 0;
2590  int min = 99999;
2591  int range = 0;
2592  int addflag = 0;
2593  std::vector<int> foundZones;
2594 
2595  for (auto itr = pConnVec.begin(); itr != pConnVec.end(); ++itr) {
2596  if (idCount != -1) {
2597  if (*itr > max && addflag) {
2598  max = *itr;
2599  pconnProcMax[proc] = max;
2600  } else if (*itr < min && addflag) {
2601  min = *itr;
2602  pconnProcMin[proc] = min;
2603  }
2604  if (!old2New.empty()) {
2605  idTmp.push_back(old2New.at(*itr));
2606  } else {
2607  idTmp.push_back(*itr);
2608  }
2609  idCount++;
2610  }
2611  if (zoneCount == 1) {
2612  currZone = *itr;
2613  auto it = find(foundZones.begin(), foundZones.end(), *itr);
2614  if (it != foundZones.end()) {
2615  addflag = 0;
2616  } else {
2617  addflag = 1;
2618  foundZones.push_back(*itr);
2619  }
2620  }
2621  if (zoneCount == 2) {
2622  range = *itr;
2623  idCount = 0;
2624  }
2625  if (idCount == range) {
2626  idCount = -1;
2627  zoneCount = 0;
2628  zoneToBlocks[currZone].push_back(idTmp);
2629  idTmp.clear();
2630  } else {
2631  zoneCount++;
2632  }
2633  }
2634 
2635  if (volOrSurf == 0) {
2636  std::vector<int> volPconnsTmpProc;
2637 
2638  // Create new Pconn vector
2639  for (int iBlock = 0; iBlock < 5; iBlock++) {
2640  volPconnsTmpProc.push_back(zoneToBlocks.size());
2641  if (iBlock > 0) {
2642  nGhost++;
2643  }
2644  if (iBlock == 0) {
2645  if ((zoneToBlocks.size()) < pconnProcMin[proc]) {
2646  pconnProcMin[proc] = zoneToBlocks.size();
2647  }
2648  if ((zoneToBlocks.size()) > pconnProcMax[proc]) {
2649  pconnProcMax[proc] = zoneToBlocks.size();
2650  }
2651  }
2652  for (auto itr1 = zoneToBlocks.begin(); itr1 != zoneToBlocks.end();
2653  ++itr1) {
2654  volPconnsTmpProc.push_back(itr1->first);
2655  if (iBlock > 0) {
2656  nGhost++;
2657  }
2658  if (iBlock == 0) {
2659  if ((itr1->first) < pconnProcMin[proc]) {
2660  pconnProcMin[proc] = itr1->first;
2661  }
2662  if ((itr1->first) > pconnProcMax[proc]) {
2663  pconnProcMax[proc] = itr1->first;
2664  }
2665  }
2666 
2667  if (itr1->second.size() > iBlock) {
2668  if (!(itr1->second)[iBlock].empty()) {
2669  volPconnsTmpProc.push_back((itr1->second)[iBlock].size());
2670  if (iBlock > 0) {
2671  nGhost++;
2672  }
2673  for (auto itr2 = (itr1->second)[iBlock].begin();
2674  itr2 != (itr1->second)[iBlock].end(); ++itr2) {
2675  volPconnsTmpProc.push_back(*itr2);
2676  if (iBlock > 0) {
2677  nGhost++;
2678  }
2679  if (iBlock == 0) {
2680  if ((*itr2) < pconnProcMin[proc]) {
2681  pconnProcMin[proc] = *itr2;
2682  }
2683  if ((*itr2) > pconnProcMax[proc]) {
2684  pconnProcMax[proc] = *itr2;
2685  }
2686  }
2687  }
2688  } else {
2689  volPconnsTmpProc.push_back(0);
2690  if (iBlock > 0) {
2691  nGhost++;
2692  }
2693  }
2694  } else {
2695  volPconnsTmpProc.push_back(0);
2696  if (iBlock > 0) {
2697  nGhost++;
2698  }
2699  }
2700  }
2701  }
2702  pConnVec = volPconnsTmpProc;
2703  } else {
2704  std::vector<int> surfPconnsTmpProc;
2705 
2706  // Create new Pconn vector
2707  for (int iBlock = 0; iBlock < 1; iBlock++) {
2708  surfPconnsTmpProc.push_back(zoneToBlocks.size());
2709  if (iBlock == 0) {
2710  if ((zoneToBlocks.size()) < pconnProcMin[proc]) {
2711  pconnProcMin[proc] = zoneToBlocks.size();
2712  }
2713  if ((zoneToBlocks.size()) > pconnProcMax[proc]) {
2714  pconnProcMax[proc] = zoneToBlocks.size();
2715  }
2716  }
2717  for (auto itr1 = zoneToBlocks.begin(); itr1 != zoneToBlocks.end();
2718  ++itr1) {
2719  surfPconnsTmpProc.push_back(itr1->first);
2720  if (iBlock == 0) {
2721  if ((itr1->first) < pconnProcMin[proc]) {
2722  pconnProcMin[proc] = itr1->first;
2723  }
2724  if ((itr1->first) > pconnProcMax[proc]) {
2725  pconnProcMax[proc] = itr1->first;
2726  }
2727  }
2728  if (itr1->second.size() > iBlock) {
2729  if (!(itr1->second)[iBlock].empty()) {
2730  surfPconnsTmpProc.push_back((itr1->second)[iBlock].size());
2731  for (auto itr2 = (itr1->second)[iBlock].begin();
2732  itr2 != (itr1->second)[iBlock].end(); ++itr2) {
2733  surfPconnsTmpProc.push_back(*itr2);
2734  if (iBlock == 0) {
2735  if ((*itr2) < pconnProcMin[proc]) {
2736  pconnProcMin[proc] = *itr2;
2737  }
2738  if ((*itr2) > pconnProcMax[proc]) {
2739  pconnProcMax[proc] = *itr2;
2740  }
2741  }
2742  }
2743  } else {
2744  surfPconnsTmpProc.push_back(0);
2745  }
2746  } else {
2747  surfPconnsTmpProc.push_back(0);
2748  }
2749  }
2750  }
2751  pConnVec = surfPconnsTmpProc;
2752  }
2753 }
2754 
2755 void RocPartCommGenRunner::clearPconnVectors() {
2756  sharedNodesTmp.clear();
2757  sentNodesTmp.clear();
2758  receivedNodesTmp.clear();
2759  sentCellsTmp.clear();
2760  receivedCellsTmp.clear();
2761 }
2762 
2763 void RocPartCommGenRunner::clearBorderVector() { neighborProcsTmp.clear(); }
2764 
2765 // Assumes one region per process (i.e. a one-to-one mapping between
2766 // partitions and processes)
2767 void RocPartCommGenRunner::mapWriter() const {
2768  // Get number of partitions
2769  int nPart = this->partitions.size();
2770 
2771  // Create mapping file
2772  std::string fname = prefixPath + this->caseName + ".map";
2773  std::ofstream mapFile;
2774  mapFile.open(fname);
2775 
2776  // Write header
2777  mapFile << "# ROCFLU region mapping file"
2778  << "\n";
2779 
2780  // Write number of regions
2781  mapFile << "# Number of regions"
2782  << "\n";
2783  mapFile << std::setw(7) << std::to_string(nPart) << "\n";
2784 
2785  // Write number of processes
2786  mapFile << "# Number of processes"
2787  << "\n";
2788  mapFile << std::setw(7) << std::to_string(nPart) << "\n";
2789 
2790  // Write process information
2791  for (int iPart = 1; iPart < nPart + 1; iPart++) {
2792  std::string procStr = std::to_string(iPart);
2793  std::string procStrPadded =
2794  std::string(6 - procStr.length(), '0') + procStr;
2795  mapFile << "# Process " << procStrPadded << "\n";
2796 
2797  mapFile << std::setw(7) << std::to_string(1) << "\n";
2798  mapFile << std::setw(7) << std::to_string(iPart) << "\n";
2799  }
2800 
2801  mapFile << "# End" << std::endl;
2802 
2803  mapFile.close();
2804 }
2805 
2806 // Cell mapping file
2807 // Currently only supports tetrahedral elements
2808 void RocPartCommGenRunner::cmpWriter(int proc, int nCells) const {
2809  // Get number of partitions
2810  // int nPart = this->partitions.size();
2811 
2812  // Write cell mapping file
2813  std::string procStr = std::to_string(proc);
2814  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
2815  std::string fname = prefixPath + this->caseName + ".cmp_" + procStrPadded;
2816  std::ofstream cmpFile;
2817  cmpFile.open(fname);
2818 
2819  // Write header
2820  cmpFile << "# ROCFLU cell mapping file"
2821  << "\n";
2822  cmpFile << "# Dimensions"
2823  << "\n";
2824  cmpFile << std::setw(8) << std::to_string(nCells) << std::setw(8)
2825  << std::to_string(0) << std::setw(8) << std::to_string(0)
2826  << std::setw(8) << std::to_string(0) << "\n";
2827  cmpFile << "# Tetrahedra"
2828  << "\n";
2829  std::string tmpStr;
2830  std::string cellStr;
2831  for (int iCell = 1; iCell < nCells + 1; iCell++) {
2832  cellStr = std::to_string(iCell);
2833  tmpStr += std::string(8 - cellStr.length(), ' ') + cellStr;
2834  if ((iCell) % 10 == 0) {
2835  cmpFile << tmpStr << "\n";
2836  tmpStr = "";
2837  }
2838  }
2839  if (!tmpStr.empty()) {
2840  cmpFile << tmpStr << "\n";
2841  tmpStr = "";
2842  }
2843  cmpFile << "# End" << std::endl;
2844  cmpFile.close();
2845 }
2846 
2847 // Write communication file
2848 // This data is the same as in PaneData/pconn in the fluid CGNS files
2849 void RocPartCommGenRunner::comWriter(int proc) const {
2850  // Get number of partitions
2851  // int nPart = this->partitions.size();
2852 
2853  // Set number of borders for each proc
2854  // int nBorders[partitions.size()];
2855  std::vector<int> nBorders;
2856  nBorders.resize(partitions.size(), 0);
2857  memset(&nBorders[0], 0, partitions.size() * sizeof(int));
2858  for (int i = 0; i < partitions.size(); i++) {
2859  nBorders[i] = 1;
2860  }
2861 
2862  // Write com file for this proc
2863  std::string procStr = std::to_string(proc);
2864  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
2865  std::string fname = prefixPath + this->caseName + ".com_" + procStrPadded;
2866  std::ofstream comFile;
2867  comFile.open(fname);
2868 
2869  // Write header
2870  comFile << "# ROCFLU communication lists file"
2871  << "\n";
2872 
2873  // Write number of neighboring procs
2874  comFile << "# Dimensions"
2875  << "\n";
2876  comFile << std::setw(8) << std::to_string(this->neighborProcsTmp.size())
2877  << "\n";
2878 
2879  // Write number of borders
2880  comFile << "# Information"
2881  << "\n";
2882  std::string tmpStr;
2883  std::string borderStr;
2884  for (auto itr = this->neighborProcsTmp.begin(); itr != neighborProcsTmp.end();
2885  ++itr) {
2886  tmpStr = "";
2887  procStr = std::to_string((*itr) + 1);
2888  borderStr = std::to_string(nBorders[*itr]);
2889  tmpStr += std::string(8 - procStr.length(), ' ') + procStr;
2890  tmpStr += std::string(8 - borderStr.length(), ' ') + borderStr;
2891  comFile << tmpStr << "\n";
2892  nBorders[*itr] += 1;
2893  }
2894 
2895  // Write cell information
2896  comFile << "# Cells"
2897  << "\n";
2898  tmpStr = "";
2899  std::string cellIdStr;
2900  std::string cellStr1;
2901  std::string cellStr2;
2902 
2903  for (auto itr = this->neighborProcsTmp.begin(); itr != neighborProcsTmp.end();
2904  ++itr) {
2905  if (this->sentCellsTmp.find(*itr) == this->sentCellsTmp.end()) {
2906  cellStr1 = std::to_string(0);
2907  } else {
2908  cellStr1 = std::to_string(this->sentCellsTmp.at(*itr).size());
2909  }
2910  if (this->receivedCellsTmp.find(*itr) == this->receivedCellsTmp.end()) {
2911  cellStr2 = std::to_string(0);
2912  } else {
2913  cellStr2 = std::to_string(this->receivedCellsTmp.at(*itr).size());
2914  }
2915  tmpStr += std::string(8 - cellStr1.length(), ' ') + cellStr1;
2916  tmpStr += std::string(8 - cellStr2.length(), ' ') + cellStr2;
2917  comFile << tmpStr << "\n";
2918  tmpStr = "";
2919 
2920  if (!(this->sentCellsTmp.find(*itr) == this->sentCellsTmp.end())) {
2921  for (auto itr2 = sentCellsTmp.at(*itr).begin();
2922  itr2 < sentCellsTmp.at(*itr).end(); ++itr2) {
2923  cellIdStr = std::to_string(*itr2);
2924  tmpStr += std::string(8 - cellIdStr.length(), ' ') + cellIdStr;
2925  if (((itr2 - sentCellsTmp.at(*itr).begin()) + 1) % 10 == 0) {
2926  comFile << tmpStr << "\n";
2927  tmpStr = "";
2928  }
2929  }
2930  if (!tmpStr.empty()) {
2931  comFile << tmpStr << "\n";
2932  tmpStr = "";
2933  }
2934  } else {
2935  comFile << tmpStr << "\n";
2936  tmpStr = "";
2937  }
2938 
2939  if (!(this->receivedCellsTmp.find(*itr) == this->receivedCellsTmp.end())) {
2940  for (auto itr2 = receivedCellsTmp.at(*itr).begin();
2941  itr2 < receivedCellsTmp.at(*itr).end(); ++itr2) {
2942  cellIdStr = std::to_string(*itr2);
2943  tmpStr += std::string(8 - cellIdStr.length(), ' ') + cellIdStr;
2944  if (((itr2 - receivedCellsTmp.at(*itr).begin()) + 1) % 10 == 0)
2945  // if (((itr2 - itr->second.begin()) + 1) % 10 == 0)
2946  {
2947  comFile << tmpStr << "\n";
2948  tmpStr = "";
2949  }
2950  }
2951  if (!tmpStr.empty()) {
2952  comFile << tmpStr << "\n";
2953  tmpStr = "";
2954  }
2955  } else {
2956  comFile << tmpStr << "\n";
2957  tmpStr = "";
2958  }
2959  }
2960 
2961  // Write node information
2962  comFile << "# Vertices"
2963  << "\n";
2964  tmpStr = "";
2965  std::string vertIdStr;
2966  std::string vertStr1;
2967  std::string vertStr2;
2968  std::string vertStr3;
2969 
2970  for (auto itr = this->neighborProcsTmp.begin(); itr != neighborProcsTmp.end();
2971  ++itr) {
2972  if (this->sentNodesTmp.find(*itr) == this->sentNodesTmp.end()) {
2973  vertStr1 = std::to_string(0);
2974  } else {
2975  vertStr1 = std::to_string(this->sentNodesTmp.at(*itr).size());
2976  }
2977 
2978  if (this->receivedNodesTmp.find(*itr) == this->receivedNodesTmp.end()) {
2979  vertStr2 = std::to_string(0);
2980  } else {
2981  vertStr2 = std::to_string(this->receivedNodesTmp.at(*itr).size());
2982  }
2983 
2984  if (this->sharedNodesTmp.find(*itr) == this->sharedNodesTmp.end()) {
2985  vertStr3 = std::to_string(0);
2986  } else {
2987  vertStr3 = std::to_string(this->sharedNodesTmp.at(*itr).size());
2988  }
2989 
2990  tmpStr += std::string(8 - vertStr1.length(), ' ') + vertStr1;
2991  tmpStr += std::string(8 - vertStr2.length(), ' ') + vertStr2;
2992  tmpStr += std::string(8 - vertStr3.length(), ' ') + vertStr3;
2993  comFile << tmpStr << "\n";
2994  tmpStr = "";
2995 
2996  if (!(this->sentNodesTmp.find(*itr) == this->sentNodesTmp.end())) {
2997  for (auto itr2 = sentNodesTmp.at(*itr).begin();
2998  itr2 < sentNodesTmp.at(*itr).end(); ++itr2) {
2999  vertIdStr = std::to_string(*itr2);
3000  tmpStr += std::string(8 - vertIdStr.length(), ' ') + vertIdStr;
3001  if (((itr2 - sentNodesTmp.at(*itr).begin()) + 1) % 10 == 0) {
3002  comFile << tmpStr << "\n";
3003  tmpStr = "";
3004  }
3005  }
3006  if (!tmpStr.empty()) {
3007  comFile << tmpStr << "\n";
3008  tmpStr = "";
3009  }
3010  } else {
3011  comFile << tmpStr << "\n";
3012  tmpStr = "";
3013  }
3014 
3015  if (!(this->receivedNodesTmp.find(*itr) == this->receivedNodesTmp.end())) {
3016  for (auto itr2 = receivedNodesTmp.at(*itr).begin();
3017  itr2 < receivedNodesTmp.at(*itr).end(); ++itr2) {
3018  vertIdStr = std::to_string(*itr2);
3019  tmpStr += std::string(8 - vertIdStr.length(), ' ') + vertIdStr;
3020  if (((itr2 - receivedNodesTmp.at(*itr).begin()) + 1) % 10 == 0) {
3021  comFile << tmpStr << "\n";
3022  tmpStr = "";
3023  }
3024  }
3025  if (!tmpStr.empty()) {
3026  comFile << tmpStr << "\n";
3027  tmpStr = "";
3028  }
3029  } else {
3030  comFile << tmpStr << "\n";
3031  tmpStr = "";
3032  }
3033 
3034  if (!(this->sharedNodesTmp.find(*itr) == this->sharedNodesTmp.end())) {
3035  for (auto itr2 = sharedNodesTmp.at(*itr).begin();
3036  itr2 < sharedNodesTmp.at(*itr).end(); ++itr2) {
3037  vertIdStr = std::to_string(*itr2);
3038  tmpStr += std::string(8 - vertIdStr.length(), ' ') + vertIdStr;
3039  if (((itr2 - sharedNodesTmp.at(*itr).begin()) + 1) % 10 == 0) {
3040  comFile << tmpStr << "\n";
3041  tmpStr = "";
3042  }
3043  }
3044  if (!tmpStr.empty()) {
3045  comFile << tmpStr << "\n";
3046  tmpStr = "";
3047  }
3048  } else {
3049  comFile << tmpStr << "\n";
3050  tmpStr = "";
3051  }
3052  }
3053 
3054  comFile << "# End" << std::endl;
3055  comFile.close();
3056 }
3057 
3058 // Rocflu dimensions file
3059 void RocPartCommGenRunner::dimWriter(int proc, std::shared_ptr<meshBase> realMB,
3060  std::shared_ptr<meshBase> totalMB) const {
3061  // Set number of borders for each proc
3062  // int nBorders[partitions.size()];
3063  std::vector<double> nBorders;
3064  nBorders.resize(partitions.size(), 0.);
3065  memset(&nBorders[0], 0, partitions.size() * sizeof(int));
3066 
3067  for (int i = 0; i < partitions.size(); i++) {
3068  nBorders[i] = 1;
3069  }
3070 
3071  // Write com file for this proc
3072  std::string procStr = std::to_string(proc);
3073  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
3074  std::string fname =
3075  prefixPath + this->caseName + ".dim_" + procStrPadded + "_0.00000E+00";
3076  std::ofstream dimFile;
3077  dimFile.open(fname);
3078 
3079  // Write vertices
3080  dimFile << "# ROCFLU dimensions file"
3081  << "\n";
3082 
3083  // Write cells
3084  dimFile << "# Vertices"
3085  << "\n";
3086  dimFile << std::setw(8)
3087  << std::to_string(realMB->getDataSet()->GetNumberOfPoints());
3088  dimFile << std::setw(8)
3089  << std::to_string(totalMB->getDataSet()->GetNumberOfPoints());
3090  dimFile << std::setw(8)
3091  << std::to_string(totalMB->getDataSet()->GetNumberOfPoints() * 4)
3092  << "\n";
3093 
3094  // Write header
3095  dimFile << "# Cells"
3096  << "\n";
3097  dimFile << std::setw(8)
3098  << std::to_string(realMB->getDataSet()->GetNumberOfCells());
3099  dimFile << std::setw(8)
3100  << std::to_string(totalMB->getDataSet()->GetNumberOfCells());
3101  dimFile << std::setw(8)
3102  << std::to_string(totalMB->getDataSet()->GetNumberOfCells() * 4)
3103  << "\n";
3104 
3105  // Write tetrahedra (currently supports only tetrahedra)
3106  dimFile << "# Tetrahedra"
3107  << "\n";
3108  dimFile << std::setw(8)
3109  << std::to_string(realMB->getDataSet()->GetNumberOfCells());
3110  dimFile << std::setw(8)
3111  << std::to_string(totalMB->getDataSet()->GetNumberOfCells());
3112  dimFile << std::setw(8)
3113  << std::to_string(totalMB->getDataSet()->GetNumberOfCells() * 4)
3114  << "\n";
3115 
3116  // Write hexahedra (not supported)
3117  dimFile << "# Hexahedra"
3118  << "\n";
3119  dimFile << std::setw(8) << "0";
3120  dimFile << std::setw(8) << "0";
3121  dimFile << std::setw(8) << "0"
3122  << "\n";
3123 
3124  // Write prisms (not supported)
3125  dimFile << "# Prisms"
3126  << "\n";
3127  dimFile << std::setw(8) << "0";
3128  dimFile << std::setw(8) << "0";
3129  dimFile << std::setw(8) << "0"
3130  << "\n";
3131 
3132  // Write pyramids (not supported)
3133  dimFile << "# Pyramids"
3134  << "\n";
3135  dimFile << std::setw(8) << "0";
3136  dimFile << std::setw(8) << "0";
3137  dimFile << std::setw(8) << "0"
3138  << "\n";
3139 
3140  // Write patches
3141  dimFile << "# Patches (v2)"
3142  << "\n";
3143 
3144  // Write borders
3145  dimFile << "# Borders"
3146  << "\n";
3147  if (proc == 0) {
3148  dimFile << std::setw(8) << "0"
3149  << "\n";
3150  } else {
3151  // Write number of neighboring procs
3152  dimFile << std::setw(8) << std::to_string(this->neighborProcsTmp.size())
3153  << "\n";
3154 
3155  // Write number of borders
3156  std::string tmpStr;
3157  std::string borderStr;
3158  std::string cellStr1;
3159  std::string cellStr2;
3160  std::string vertStr1;
3161  std::string vertStr2;
3162  std::string vertStr3;
3163  for (auto itr = this->neighborProcsTmp.begin();
3164  itr != neighborProcsTmp.end(); ++itr) {
3165  tmpStr = "";
3166 
3167  // proc/border information
3168  procStr = std::to_string((*itr) + 1);
3169  borderStr = std::to_string(nBorders[*itr]);
3170  tmpStr += std::string(8 - procStr.length(), ' ') + procStr;
3171  tmpStr += std::string(8 - borderStr.length(), ' ') + borderStr;
3172  nBorders[*itr] += 1;
3173 
3174  // sent, received cells
3175  if (this->sentCellsTmp.find(*itr) == this->sentCellsTmp.end()) {
3176  cellStr1 = std::to_string(0);
3177  } else {
3178  cellStr1 = std::to_string(this->sentCellsTmp.at(*itr).size());
3179  }
3180  if (this->receivedCellsTmp.find(*itr) == this->receivedCellsTmp.end()) {
3181  cellStr2 = std::to_string(0);
3182  } else {
3183  cellStr2 = std::to_string(this->receivedCellsTmp.at(*itr).size());
3184  }
3185  tmpStr += std::string(8 - cellStr1.length(), ' ') + cellStr1;
3186  tmpStr += std::string(8 - cellStr2.length(), ' ') + cellStr2;
3187 
3188  // sent, received, shared vertices
3189  if (this->sentNodesTmp.find(*itr) == this->sentNodesTmp.end()) {
3190  vertStr1 = std::to_string(0);
3191  } else {
3192  vertStr1 = std::to_string(this->sentNodesTmp.at(*itr).size());
3193  }
3194  if (this->receivedNodesTmp.find(*itr) == this->receivedNodesTmp.end()) {
3195  vertStr2 = std::to_string(0);
3196  } else {
3197  vertStr2 = std::to_string(this->receivedNodesTmp.at(*itr).size());
3198  }
3199  if (this->sharedNodesTmp.find(*itr) == this->sharedNodesTmp.end()) {
3200  vertStr3 = std::to_string(0);
3201  } else {
3202  vertStr3 = std::to_string(this->sharedNodesTmp.at(*itr).size());
3203  }
3204  tmpStr += std::string(8 - vertStr1.length(), ' ') + vertStr1;
3205  tmpStr += std::string(8 - vertStr2.length(), ' ') + vertStr2;
3206  tmpStr += std::string(8 - vertStr3.length(), ' ') + vertStr3;
3207 
3208  dimFile << tmpStr << "\n";
3209  }
3210  }
3211 
3212  // Write borders
3213  dimFile << "# End" << std::endl;
3214  dimFile.close();
3215 }
3216 
3217 // Write surface information for Rocstar dimension file
3218 void RocPartCommGenRunner::dimSurfWriter(
3219  int proc, const std::vector<cgsize_t> &cgConnReal,
3220  const std::vector<cgsize_t> &cgConnVirtual, int patchNo) {
3221  // Write com file for this proc
3222  std::string procStr = std::to_string(proc);
3223  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
3224  std::string fname =
3225  prefixPath + this->caseName + ".dim_" + procStrPadded + "_0.00000E+00";
3226 
3227  std::string line;
3228  std::vector<std::string> myLines;
3229  std::ifstream myfile(fname);
3230 
3231  // Get current dim file
3232  while (std::getline(myfile, line)) myLines.push_back(line);
3233 
3234  // Accumulate all patches
3235  std::set<int> patches;
3236  for (auto itr = patchesOfSurfacePartitions.begin();
3237  itr != patchesOfSurfacePartitions.end(); ++itr)
3238  for (auto itr2 = (*itr).begin(); itr2 != (*itr).end(); ++itr2)
3239  patches.insert(itr2->first);
3240 
3241  // Insert Patch lines in existing file
3242  std::vector<std::string> newLines;
3243  std::string patchStr1;
3244  std::string patchStr2;
3245  std::string patchStr3;
3246  std::string patchStr4;
3247  std::string tmpStr;
3248  for (auto itr = myLines.begin(); itr != myLines.end(); ++itr) {
3249  if ((*itr).find("Borders") != std::string::npos) {
3250  if ((*(itr - 1)).find("Patches (v2)") != std::string::npos) {
3251  tmpStr = "";
3252  patchStr1 =
3253  std::to_string(this->patchesOfSurfacePartitions[proc - 1].size());
3254  patchStr2 = std::to_string(*patches.rbegin());
3255  tmpStr += std::string(8 - patchStr1.length(), ' ') + patchStr1;
3256  tmpStr += std::string(8 - patchStr2.length(), ' ') + patchStr2;
3257  newLines.push_back(tmpStr);
3258  }
3259  for (auto itr2 = this->patchesOfSurfacePartitions[proc - 1].begin();
3260  itr2 != this->patchesOfSurfacePartitions[proc - 1].end(); ++itr2) {
3261  if (itr2->first == patchNo) {
3262  this->totalTrisPerPatch[patchNo] +=
3263  cgConnReal.size() + cgConnVirtual.size();
3264  tmpStr = "";
3265  patchStr1 = std::to_string(itr2->first);
3266  tmpStr += std::string(8 - patchStr1.length(), ' ') + patchStr1;
3267  patchStr2 = std::to_string(cgConnReal.size() / 3);
3268  tmpStr += std::string(8 - patchStr2.length(), ' ') + patchStr2;
3269  patchStr3 =
3270  std::to_string((cgConnReal.size() + cgConnVirtual.size()) / 3);
3271  tmpStr += std::string(8 - patchStr3.length(), ' ') + patchStr3;
3272  patchStr4 = std::to_string(
3273  4 * (cgConnReal.size() + cgConnVirtual.size()) / 3);
3274  tmpStr += std::string(8 - patchStr4.length(), ' ') + patchStr4;
3275  tmpStr += std::string(8 - 1, ' ') + '0';
3276  tmpStr += std::string(8 - 1, ' ') + '0';
3277  tmpStr += std::string(8 - 1, ' ') + '0';
3278  tmpStr += std::string(8 - 1, ' ') + '0';
3279  newLines.push_back(tmpStr);
3280  }
3281  }
3282  }
3283  newLines.push_back(*itr);
3284  }
3285 
3286  // Write new lines to file
3287  std::ofstream dimFile;
3288  dimFile.open(fname);
3289  for (auto itr = newLines.begin(); itr != newLines.end(); ++itr)
3290  dimFile << *itr << "\n";
3291  dimFile.close();
3292 }
3293 
3294 // Write surface information for Rocstar dimension file
3295 void RocPartCommGenRunner::dimSurfWriter(int proc) const {
3296  // Write com file for this proc
3297  std::string procStr = std::to_string(proc);
3298  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
3299  std::string fname =
3300  prefixPath + this->caseName + ".dim_" + procStrPadded + "_0.00000E+00";
3301 
3302  std::string line;
3303  std::vector<std::string> myLines;
3304  std::ifstream myfile(fname);
3305 
3306  // Get current dim file
3307  while (std::getline(myfile, line)) {
3308  myLines.push_back(line);
3309  }
3310 
3311  // Accumulate all patches
3312  std::set<int> patches;
3313  for (auto itr = patchesOfSurfacePartitions.begin();
3314  itr != patchesOfSurfacePartitions.end(); ++itr) {
3315  for (auto itr2 = (*itr).begin(); itr2 != (*itr).end(); ++itr2) {
3316  patches.insert(itr2->first);
3317  }
3318  }
3319 
3320  // Insert Patch lines in existing file
3321  std::vector<std::string> newLines;
3322  std::string patchStr1;
3323  std::string patchStr2;
3324  std::string patchStr3;
3325  std::string patchStr4;
3326  std::string tmpStr;
3327  for (auto itr = myLines.begin(); itr != myLines.end(); ++itr) {
3328  if ((*itr).find("Borders") != std::string::npos) {
3329  if ((*(itr - 1)).find("Patches (v2)") != std::string::npos) {
3330  tmpStr = "";
3331  patchStr1 = std::to_string(*patches.rbegin());
3332  tmpStr += std::string(8 - patchStr1.length(), ' ') + patchStr1;
3333  tmpStr += std::string(8 - patchStr1.length(), ' ') + patchStr1;
3334  newLines.push_back(tmpStr);
3335  }
3336  for (auto itr2 = patches.begin(); itr2 != patches.end(); ++itr2) {
3337  tmpStr = "";
3338  patchStr1 = std::to_string(*itr2);
3339  tmpStr += std::string(8 - patchStr1.length(), ' ') + patchStr1;
3340  patchStr2 = std::to_string((this->totalTrisPerPatch.at(*itr2)) / 3);
3341  tmpStr += std::string(8 - patchStr2.length(), ' ') + patchStr2;
3342  patchStr3 = std::to_string((this->totalTrisPerPatch.at(*itr2)) / 3);
3343  tmpStr += std::string(8 - patchStr3.length(), ' ') + patchStr3;
3344  patchStr4 = std::to_string(4 * (this->totalTrisPerPatch.at(*itr2)) / 3);
3345  tmpStr += std::string(8 - patchStr4.length(), ' ') + patchStr4;
3346  tmpStr += std::string(8 - 1, ' ') + '0';
3347  tmpStr += std::string(8 - 1, ' ') + '0';
3348  tmpStr += std::string(8 - 1, ' ') + '0';
3349  tmpStr += std::string(8 - 1, ' ') + '0';
3350  newLines.push_back(tmpStr);
3351  }
3352  }
3353  newLines.push_back(*itr);
3354  }
3355 
3356  // Write new lines to file
3357  std::ofstream dimFile;
3358  dimFile.open(fname);
3359  for (auto itr = newLines.begin(); itr != newLines.end(); ++itr) {
3360  dimFile << *itr << "\n";
3361  }
3362 
3363  dimFile.close();
3364 }
3365 
3366 void RocPartCommGenRunner::txtWriter() const {
3367  // Write txt files for fluid and ifluid
3368  std::string fname;
3369  fname = prefixPath + "fluid_in_" + this->base_t + ".txt";
3370  std::ofstream fluid_in;
3371  fluid_in.open(fname);
3372 
3373  fname = prefixPath + "ifluid_in_" + this->base_t + ".txt";
3374  std::ofstream ifluid_in;
3375  ifluid_in.open(fname);
3376 
3377  fname = prefixPath + "burn_in_" + this->base_t + ".txt";
3378  std::ofstream burn_in;
3379  burn_in.open(fname);
3380 
3381  fname = prefixPath + "iburn_in_" + this->base_t + ".txt";
3382  std::ofstream iburn_in;
3383  iburn_in.open(fname);
3384 
3385  // Get number of partitions
3386  int nPart = this->partitions.size();
3387 
3388  std::string tmpStr;
3389  std::string paneStr;
3390  for (int iPart = 0; iPart < nPart; iPart++) {
3391  // Write to fluid file
3392  fluid_in << "@Proc: " << std::to_string(iPart) << "\n";
3393  fluid_in << "@Files: fluid_" + this->base_t + "_%04p.cgns"
3394  << "\n";
3395  tmpStr = "@Panes:";
3396  tmpStr += " " + std::to_string(volZoneMap[iPart]) + "\n";
3397  fluid_in << tmpStr << std::endl;
3398 
3399  // Write to ifluid_file
3400  ifluid_in << "@Proc: " << std::to_string(iPart) << "\n";
3401  ;
3402  ifluid_in << "@Files: ifluid*_" + this->base_t + "_%04p.cgns"
3403  << "\n";
3404  tmpStr = "@Panes:";
3405  int burnFlag;
3406  std::string burnStrTmp;
3407  for (auto itr1 = surfZoneMap[iPart].begin();
3408  itr1 != surfZoneMap[iPart].end(); ++itr1) {
3409  burnFlag = 0;
3410  if (std::find(surfacePatchTypes.at("Burning").begin(),
3411  surfacePatchTypes.at("Burning").end(),
3412  itr1->first) != surfacePatchTypes.at("Burning").end()) {
3413  burnFlag = 1;
3414  }
3415  tmpStr += " " + std::to_string(iPart + 1);
3416  if (burnFlag) burnStrTmp += " " + std::to_string(iPart + 1);
3417  if ((itr1->second) < 10) {
3418  tmpStr += "0";
3419  if (burnFlag) burnStrTmp += "0";
3420  }
3421  tmpStr += std::to_string(itr1->second);
3422  if (burnFlag) burnStrTmp += std::to_string(itr1->second);
3423  }
3424 
3425  tmpStr += "\n";
3426  ifluid_in << tmpStr << std::endl;
3427 
3428  // Write to burn_file
3429  iburn_in << "@Proc: " << std::to_string(iPart) << "\n";
3430  if (burnStrTmp.empty()) {
3431  iburn_in << "@Files:"
3432  << "\n";
3433  } else {
3434  iburn_in << "@Files: iburn*_" + this->base_t + "_%04p.cgns"
3435  << "\n";
3436  }
3437  tmpStr = "@Panes:";
3438  tmpStr += burnStrTmp;
3439  tmpStr += "\n";
3440  iburn_in << tmpStr << std::endl;
3441 
3442  // Write to iburn_file
3443  burn_in << "@Proc: " << std::to_string(iPart) << "\n";
3444  if (burnStrTmp.empty()) {
3445  burn_in << "@Files:"
3446  << "\n";
3447  } else {
3448  burn_in << "@Files: burn*_" + this->base_t + "_%04p.cgns"
3449  << "\n";
3450  }
3451  tmpStr = "@Panes:";
3452  tmpStr += burnStrTmp;
3453  tmpStr += "\n";
3454  burn_in << tmpStr << std::endl;
3455  }
3456  fluid_in.close();
3457  ifluid_in.close();
3458 }
3459 
3460 void RocPartCommGenRunner::swapTriOrdering(
3461  std::vector<cgsize_t> &connVec) const {
3462  // Change ordering from counter-clockwise to clockwise convention
3463  std::vector<cgsize_t> connVecTmp;
3464  int ind = 1;
3465  int tmpInd = -1;
3466  for (auto itr = connVec.begin(); itr != connVec.end(); ++itr) {
3467  if (ind == 1) {
3468  connVecTmp.push_back(*itr);
3469  ind++;
3470  } else if (ind == 2) {
3471  tmpInd = *itr;
3472  ind++;
3473  } else if (ind == 3) {
3474  connVecTmp.push_back(*itr);
3475  connVecTmp.push_back(tmpInd);
3476  ind = 1;
3477  }
3478  }
3479  connVec = connVecTmp;
3480 }
3481 
3482 std::string RocPartCommGenRunner::getPatchType(int patchNo) const {
3483  if (std::find(surfacePatchTypes.at("Burning").begin(),
3484  surfacePatchTypes.at("Burning").end(),
3485  patchNo) != surfacePatchTypes.at("Burning").end()) {
3486  return "ifluid_b";
3487  } else if (std::find(surfacePatchTypes.at("Non-Burning").begin(),
3488  surfacePatchTypes.at("Non-Burning").end(),
3489  patchNo) != surfacePatchTypes.at("Non-Burning").end()) {
3490  return "ifluid_nb";
3491  } else if (std::find(surfacePatchTypes.at("Non-Interacting").begin(),
3492  surfacePatchTypes.at("Non-Interacting").end(),
3493  patchNo) !=
3494  surfacePatchTypes.at("Non-Interacting").end()) {
3495  return "ifluid_ni";
3496  }
3497  std::cerr << "Error: Can't get patch type for patch number " << patchNo
3498  << std::endl;
3499  exit(1);
3500 }
3501 
3502 // Write surface information for Rocstar dimension file
3503 void RocPartCommGenRunner::dimSurfSort(int proc) const {
3504  // Write com file for this proc
3505  std::string procStr = std::to_string(proc);
3506  std::string procStrPadded = std::string(5 - procStr.length(), '0') + procStr;
3507  std::string fname =
3508  prefixPath + this->caseName + ".dim_" + procStrPadded + "_0.00000E+00";
3509 
3510  std::string line;
3511  std::vector<std::string> myLines;
3512  std::ifstream myfile(fname);
3513 
3514  // Get current dim file
3515  while (std::getline(myfile, line)) {
3516  myLines.push_back(line);
3517  }
3518 
3519  std::map<int, std::string> patchLines;
3520  int patchCounter = 0;
3521 
3522  // Get patch lines, implicitly sorted by patch number
3523  for (auto itr = myLines.begin(); itr != myLines.end(); ++itr) {
3524  if ((std::distance(myLines.begin(), itr) > 1) &&
3525  (*(itr - 1)).find("Patches (v2)") != std::string::npos) {
3526  while ((*itr).find("Borders") == std::string::npos) {
3527  if (patchCounter > 0) {
3528  std::istringstream strs(*itr);
3529  int tmp;
3530  std::vector<int> ints;
3531  while (strs >> tmp) {
3532  ints.push_back(tmp);
3533  }
3534  patchLines[ints[0]] = *itr;
3535  }
3536  patchCounter++;
3537  itr++;
3538  }
3539  }
3540  }
3541 
3542  // Insert patch lines in newly sorted order
3543  for (auto itr = myLines.begin(); itr != myLines.end(); ++itr) {
3544  if (std::distance(myLines.begin(), itr) > 2 &&
3545  (*(itr - 2)).find("Patches (v2)") != std::string::npos) {
3546  for (auto itr2 = patchLines.begin(); itr2 != patchLines.end(); ++itr2) {
3547  *itr = itr2->second;
3548  itr++;
3549  }
3550  }
3551  }
3552 
3553  // Write new lines to file
3554  std::ofstream dimFile;
3555  dimFile.open(fname);
3556  for (auto itr = myLines.begin(); itr != myLines.end(); ++itr) {
3557  dimFile << *itr << "\n";
3558  }
3559 
3560  dimFile.close();
3561 }
3562 
3563 } // namespace
3564 
3566  std::string surfName,
3567  int numPartitions)
3568  : volName(std::move(volName)),
3569  surfName(std::move(surfName)),
3570  numPartitions(numPartitions) {}
3571 
3572 jsoncons::string_view RocPartCommGenDriver::getProgramType() const {
3573  return programType;
3574 }
3575 
3577  RocPartCommGenRunner(this->volName, this->surfName, this->numPartitions);
3578 }
3579 
3580 } // namespace DRV
3581 } // namespace NEM
std::vector< std::vector< nemId_t > > globalNodeIds
std::map< int, std::map< int, std::vector< int > > > sharedSurfNodes
std::vector< std::map< nemId_t, nemId_t > > partToGlobCellMap
std::map< int, std::vector< int > > receivedCellsTmp
std::vector< std::map< int, std::map< int, std::map< int, std::vector< int > > > > > sharedPatchNodes
std::string base_t
std::vector< std::map< int, std::shared_ptr< meshBase > > > patchesOfSurfacePartitions
std::shared_ptr< meshBase > volWithSol
std::vector< std::map< nemId_t, nemId_t > > globToPartCellMap
static std::vector< std::shared_ptr< meshBase > > partition(const meshBase *mbObj, int numPartitions)
mesh partitioning (with METIS)
Definition: meshBase.C:295
std::map< int, std::map< int, std::unordered_set< int > > > sentCells
std::map< int, int > totalTrisPerPatch
std::vector< std::map< nemId_t, nemId_t > > partToGlobNodeMap
A brief description of meshBase.
Definition: meshBase.H:64
std::size_t nemId_t
Definition: meshBase.H:51
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
STL namespace.
bool smoothC2CTrans
std::map< int, std::vector< int > > receivedNodesTmp
std::map< int, std::vector< int > > sharedNodesTmp
std::vector< int > neighborProcsTmp
std::vector< std::map< int, int > > surfZoneMap
double searchTolerance
std::vector< std::vector< nemId_t > > globalCellIds
std::map< int, std::map< int, std::unordered_set< int > > > sentSurfCells
std::map< int, int > nUniqueVolFaces
std::vector< int > notGhostInPconn
std::vector< std::map< int, std::shared_ptr< meshBase > > > virtualCellsOfSurfPartitions
std::shared_ptr< meshBase > remeshedSurf
std::map< int, std::map< int, std::unordered_set< int > > > receivedCells
std::vector< std::map< int, std::shared_ptr< meshBase > > > virtualCellsOfPartitions
std::string prefixPath
std::map< int, std::map< int, std::unordered_set< int > > > receivedSurfNodes
vtkSmartPointer< vtkDataSet > getDataSet() const
get this meshes&#39; dataSet
Definition: meshBase.H:308
std::string caseName
std::string trimmed_base_t
std::map< int, std::vector< int > > sentCellsTmp
vtkIdType id
id in .inp file
Definition: inpGeoMesh.C:128
std::vector< std::shared_ptr< meshBase > > surfacePartitions
static constexpr const char * programType
std::vector< std::map< int, std::vector< int > > > surfPconns
static meshBase * stitchMB(const std::vector< meshBase *> &mbObjs)
stitch together several meshBases
Definition: meshBase.C:196
std::shared_ptr< meshBase > mesh
static std::shared_ptr< meshBase > CreateShared(const std::string &fname)
Create shared ptr from fname.
Definition: meshBase.C:171
std::map< int, std::map< int, std::unordered_set< int > > > receivedSurfCells
std::map< std::string, std::vector< int > > surfacePatchTypes
std::map< int, std::vector< int > > sentNodesTmp
std::vector< int > volZoneMap
std::vector< std::map< nemId_t, nemId_t > > globToPartNodeMap
std::vector< std::map< int, std::map< int, std::shared_ptr< meshBase > > > > virtualCellsOfPatchesOfSurfacePartitions
std::shared_ptr< meshBase > surfWithSol
void execute() const override
Run the workflow represented by the driver.
std::map< int, std::map< int, std::unordered_set< int > > > sentNodes
std::map< int, std::map< int, std::unordered_set< int > > > sentSurfNodes
std::map< int, int > pconnProcMin
static std::shared_ptr< TransferBase > CreateTransferObject(meshBase *srcmsh, meshBase *trgmsh, const std::string &method)
std::vector< std::shared_ptr< meshBase > > procVolMesh
static meshBase * extractSelectedCells(meshBase *mesh, const std::vector< nemId_t > &cellIds)
extract subset of mesh given list of cell ids and return meshBase obj
Definition: meshBase.C:226
vtkIdType currId
If previous line was data line that is continued and current keyword is NODE or ELEMEMT, the ID of the node/cell being processed.
Definition: inpGeoMesh.C:321
jsoncons::string_view getProgramType() const override
std::shared_ptr< meshBase > burnSurfWithSol
std::vector< std::map< int, int > > burnSurfZoneMap
std::vector< A > getSortedKeys(const std::map< A, B > &mapObj)
std::map< int, std::map< int, std::vector< int > > > sharedNodes
std::vector< std::vector< int > > volPconns
std::map< int, int > pconnProcMax
std::vector< std::shared_ptr< meshBase > > partitions
int writeAllFiles
std::map< int, std::map< int, std::unordered_set< int > > > receivedNodes