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.
rocPack.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 *******************************************************************************/
29 #define _USE_MATH_DEFINES
30 
31 #include <ANN/ANN.h>
32 #include <stdlib.h>
33 #include <vtkCell.h>
34 #include <vtkCell3D.h>
35 #include "AuxiliaryFunctions.H"
36 #include "Geometry/hmxShape.H"
38 #include "Geometry/petnShape.H"
39 #include "Geometry/rocPack.H"
40 #include "Geometry/rocPackShape.H"
41 #include "Mesh/vtkMesh.H"
42 
43 #include <Eigen/Geometry>
44 #include <chrono>
45 #include <fstream>
46 #include <iostream>
47 #include <map>
48 #include <sstream>
49 #include <string>
50 #include <vector>
51 
52 #include "Mesh/meshBase.H"
53 
54 // GMSH Header
55 #include <gmsh.h>
56 
57 namespace NEM {
58 
59 namespace GEO {
60 
61 // class constructor
62 rocPack::rocPack(const std::string &fname, const std::string &outName) {
63  std::cout << "rocPack class constructed!" << std::endl;
64  InFile = fname;
65  OutFile = outName;
66 }
67 
69  // Parses output file from Rocpack
70  rocParser();
71 
72  // Generates geometry from parsed database.
73  rocToGeom();
74 
75  // Generates surface mesh for created geometry and writes in surface files
76  geomToSurf();
77 
78  gmsh::finalize();
79  std::cout << " - End of process!" << std::endl;
80 }
81 
83  periodic3D = true;
84 
85  // Parses output file from Rocpack
86  rocParser();
87 
88  // Generates geometry from parsed database.
89  rocToGeom();
90 
91  // Generates 3D periodic mesh for created geometry and writes in surface files
93 
94  // Creates cohesive elements if specified
96 
97  // Writes periodic mesh maps to CSV files
99 
100  gmsh::finalize();
101  std::cout << " - End of process!" << std::endl;
102 }
103 
105 
107 
109 
111 
112 void rocPack::shrinkVolumes(const double percntg) {
113  shrinkScale = percntg;
114  enableScaling = true;
115 }
116 
117 void rocPack::smoothSurfaces(const int smoothingParam) {
118  smoothingIter = smoothingParam;
119  enableSmoothing = true;
120 }
121 
122 void rocPack::setMeshSize(const double size) { meshSz = size; }
123 
124 void rocPack::assignRefinement(const int &refineLvl) { refineIter = refineLvl; }
125 
126 void rocPack::applyFilter(const double &upperThreshold,
127  const double &lowerThreshold) {
128  filterOn = true;
129  filterAbove = upperThreshold;
130  filterBelow = lowerThreshold;
131 }
132 
134 
136 
138 
140 
141 void rocPack::setElementOrder(const int &order) { elementOrder = order; }
142 
144  gmsh::initialize();
145  gmsh::model::add("Pack");
146  gmsh::option::setNumber("General.NumThreads", 10);
147  gmsh::option::setNumber("Geometry.OCCBooleanPreserveNumbering", 1);
148  gmsh::option::setNumber("Geometry.OCCParallel", 1);
149  // if (elementOrder > 1) gmsh::option::setNumber("Mesh.HighOrderPeriodic", 2);
150 }
151 
153  // Check if file exist
154  std::cout << " - Parsing output file ... " << std::endl;
155  std::ifstream rocOut(InFile);
156  if (rocOut.is_open()) {
157  if (cstmDomain) {
158  // Nothing
159  } else {
160  // Getting box dimensions
161  std::vector<std::string> rocTokens;
162  std::string line = findWord("boundary");
163  rocTokens = nemAux::Tokenize(line, ' ');
164  if (rocTokens[6] != "periodic") {
165  std::cerr << "Please select output file with periodic geometries!"
166  << std::endl;
167  throw;
168  }
169 
170  Xdim = std::atof(nemAux::strToChar(rocTokens[3]).get());
171  Ydim = std::atof(nemAux::strToChar(rocTokens[4]).get());
172  Zdim = std::atof(nemAux::strToChar(rocTokens[5]).get());
173  boxPt.push_back((-Xdim / 2) + xUDF);
174  boxPt.push_back((-Ydim / 2) + yUDF);
175  boxPt.push_back((-Zdim / 2) + zUDF);
176  }
177 
178  // Stores all lines in file to myLines
179  std::string linesOut; // Temporary string for multiple uses
180  std::vector<std::string> myLines; // Stores whole file line by line
181  while (std::getline(rocOut, linesOut)) myLines.push_back(linesOut);
182 
183  // Checking for user-specified options
184  for (int i = 0; i < myLines.size(); i++) {
185  nemAux::toLower(myLines[i]);
186 
187  if (myLines[i].find("setperiodicity") != std::string::npos)
188  if (myLines[i].find("true") != std::string::npos)
189  enablePeriodicity = true;
190 
191  if (myLines[i].find("removeboundarypacks") != std::string::npos)
192  if (myLines[i].find("true") != std::string::npos)
193  removeBoundaryPacks = true;
194 
195  if (myLines[i].find("set scaling") != std::string::npos) {
196  std::vector<std::string> glbSclTkns;
197  glbSclTkns = nemAux::Tokenize(myLines[i], "=;");
198  globalScaling = std::atof(nemAux::strToChar(glbSclTkns[1]).get());
199  }
200  }
201 
202  if (enableSizePreserve) {
203  Xdim = Xdim * globalScaling;
204  Ydim = Ydim * globalScaling;
205  Zdim = Zdim * globalScaling;
206  boxPt[0] = boxPt[0] * globalScaling;
207  boxPt[1] = boxPt[1] * globalScaling;
208  boxPt[2] = boxPt[2] * globalScaling;
209  }
210 
211  if (periodic3D == true && enablePeriodicity == false) {
212  std::cerr << "Periodicity needed if using periodic meshing!" << std::endl
213  << "Please enable SetPeriodicity option to"
214  << " get 3D periodic mesh" << std::endl;
215  throw;
216  }
217 
218  // Checking if crystal shapes are present
219  // crystalNames and verts/faces go parallel in terms of indexing
220  int nCrystals = 0;
221  for (int i = 0; i < myLines.size(); i++) {
222  if (myLines[i].find("#import") != std::string::npos ||
223  myLines[i].find("import") == std::string::npos) {
224  // Nothing
225  } else if (myLines[i].find("import") != std::string::npos ||
226  myLines[i].find("#import") == std::string::npos) {
227  nCrystals++;
228  std::vector<std::string> importStr;
229  importStr = nemAux::Tokenize(myLines[i], "//\"");
230  crystalNames.push_back(importStr[2]);
231  } else {
232  // Nothing
233  }
234  }
235 
236  if (nCrystals > 0) {
237  verts.resize(nCrystals);
238  faces.resize(nCrystals);
239  for (int i = 0; i < nCrystals; i++) {
240  auto getData = rocPackShape::getShape(crystalNames[i]);
241  verts[i] = getData->getVertices();
242  faces[i] = getData->getFaces();
243  }
244  normalizeVerts();
245  }
246 
247  // Checking if any shapes are present. If present, extract imp data
248  for (int i = 0; i < myLines.size(); i++) {
249  if (myLines[i].find("shape ") != std::string::npos) {
250  std::vector<std::string> baseShapes;
251  baseShapes = nemAux::Tokenize(myLines[i], " ");
252  shapeNames.push_back(baseShapes[3]);
253  uniqueNames.push_back(baseShapes[1]);
254 
255  if (baseShapes[3] == "cylinder") {
256  cylParams.resize(2);
257  cylParams[0] = std::atof(nemAux::strToChar(baseShapes[5]).get());
258  cylParams[1] = std::atof(nemAux::strToChar(baseShapes[6]).get());
259  }
260 
261  if (baseShapes[3] == "ellipsoid") {
262  ellipsoidRad.resize(3);
263  ellipsoidRad[0] = std::atof(nemAux::strToChar(baseShapes[5]).get());
264  ellipsoidRad[1] = std::atof(nemAux::strToChar(baseShapes[6]).get());
265  ellipsoidRad[2] = std::atof(nemAux::strToChar(baseShapes[7]).get());
266  ellipsoidPresent = true;
267  }
268  } else {
269  }
270  }
271 
272  if (ellipsoidPresent)
273  std::cout << " !!Warning!!" << std::endl
274  << " This geometry will not be periodic due to presence of "
275  << "Ellipsoid shapes!" << std::endl
276  << " Ellipsoid shapes cannot be made periodic as of now!"
277  << std::endl;
278 
279  // Getting line number where pack data starts
280  // Also counting total number of packs
281  int numPacks = 0;
282  int iter = 0;
283  for (int i = 0; i < myLines.size(); i++) {
284  if (myLines[i].find("translate") != std::string::npos) numPacks++;
285  if (myLines[i].find("translate") != std::string::npos && iter == 0)
286  iter = i;
287  else {
288  }
289  }
290  iter = iter - 1; // Start parsing from "iter"
291 
292  // Pack shape data storage initialization
293  // Getting pack data
294  translateParams.resize(numPacks);
295  rotateParams.resize(numPacks);
296  scaleOfPack.resize(numPacks);
297  nameOfPcks.resize(numPacks);
298  int h = 0;
299  std::string pckNameStr = " ";
300  std::string translateStr = "<,,>";
301  std::string rotateStr = "<,,>";
302  std::string scaleStr = " ";
303 
304  std::vector<double> udfTranslate;
305  udfTranslate.resize(3);
306  udfTranslate[0] = xUDF;
307  udfTranslate[1] = yUDF;
308  udfTranslate[2] = zUDF;
309 
310  for (int i = iter; i < myLines.size(); i++) {
311  translateParams[h].resize(3);
312  rotateParams[h].resize(4);
313  std::vector<std::string> pckNmDataTokens;
314  pckNmDataTokens.resize(2);
315  std::vector<std::string> trnsltDataTokens;
316  trnsltDataTokens.resize(4);
317  std::vector<std::string> rttDataTokens;
318  rttDataTokens.resize(7);
319  std::vector<std::string> scaleDataTokens;
320  scaleDataTokens.resize(8);
321 
322  // Name of pack shape
323  pckNmDataTokens = getShapeData(i, pckNameStr, myLines);
324  nameOfPcks[h] = pckNmDataTokens[0];
325 
326  // Translate Parameters
327  trnsltDataTokens = getShapeData(i + 1, translateStr, myLines);
328 
329  if (enableSizePreserve) {
330  for (int j = 0; j < 3; j++)
331  translateParams[h][j] =
332  (std::atof(nemAux::strToChar(trnsltDataTokens[j + 1]).get()) *
333  globalScaling) +
334  udfTranslate[j];
335  } else {
336  for (int j = 0; j < 3; j++)
337  translateParams[h][j] =
338  std::atof(nemAux::strToChar(trnsltDataTokens[j + 1]).get()) +
339  udfTranslate[j];
340  }
341 
342  trnsltDataTokens.clear();
343 
344  // Rotate Parameters
345  rttDataTokens = getShapeData(i + 2, rotateStr, myLines);
346 
347  if (enableSizePreserve) {
348  for (int j = 0; j < 4; j++)
349  rotateParams[h][j] =
350  std::atof(nemAux::strToChar(rttDataTokens[j + 1]).get()) *
352  } else {
353  for (int j = 0; j < 4; j++)
354  rotateParams[h][j] =
355  std::atof(nemAux::strToChar(rttDataTokens[j + 1]).get());
356  }
357 
358  rttDataTokens.clear();
359 
360  scaleDataTokens = getShapeData(i + 3, scaleStr, myLines);
361 
362  // Scale Parameters
363  if (enableSizePreserve)
364  scaleOfPack[h] =
365  std::atof(nemAux::strToChar(scaleDataTokens[1]).get()) *
367  else
368  scaleOfPack[h] =
369  std::atof(nemAux::strToChar(scaleDataTokens[1]).get()) *
370  shrinkScale;
371 
372  scaleDataTokens.clear();
373 
374  i = i + 5;
375  h++;
376  }
377  rocOut.close();
378  } else {
379  std::cerr << "Cannot open/find " << InFile << " file!" << std::endl;
380  throw;
381  }
382 }
383 
384 // Loops through parsed data and makes gmsh geometries.
386  std::cout << " - Creating pack geometries ... " << std::endl;
387  // Starting Gmsh commands
388  initialize();
389 
390  filteredGeoms.resize(scaleOfPack.size());
391  for (int i = 0; i < filteredGeoms.size(); i++) filteredGeoms[i] = 1;
392 
393  if (filterOn) {
394  // Finding mean of scales
395  double mean = 0;
396  for (int i = 0; i < scaleOfPack.size(); i++) mean += scaleOfPack[i];
397 
398  mean = mean / scaleOfPack.size();
399 
400  for (int i = 0; i < scaleOfPack.size(); i++)
401  if ((scaleOfPack[i] > mean * filterAbove) ||
402  (scaleOfPack[i] < mean * filterBelow))
403  filteredGeoms[i] = 0;
404  }
405 
406  for (int i = 0; i < nameOfPcks.size(); i++) {
407  if (filteredGeoms[i] == 1) {
408  if (nameOfPcks[i] == "sphere") { makeSphere(i); }
409 
410  if (uniqueNames.size() > 0) {
411  for (int j = 0; j < uniqueNames.size(); j++) {
412  if (nameOfPcks[i] == uniqueNames[j] && shapeNames[j] == "ellipsoid")
413  makeEllipsoid(i);
414  else if (nameOfPcks[i] == uniqueNames[j] &&
415  shapeNames[j] == "cylinder")
416  makeCylinder(i);
417  else {
418  }
419  }
420  }
421 
422  if (crystalNames.size() > 0) {
423  for (int k = 0; k < crystalNames.size(); k++)
424  if (crystalNames[k] == nameOfPcks[i]) makeCrystalShape(i, k);
425  }
426  }
427  }
428 
429  // Tagging packs intersecting domain boundary
431 
432  if (removeBoundaryPacks == true && ellipsoidPresent == false) {
433  gmsh::model::occ::remove(bndryPackTags, true);
434  gmsh::model::occ::synchronize();
435  } else if (removeBoundaryPacks == true && ellipsoidPresent == true) {
436  gmsh::model::geo::remove(bndryPackTags, true);
437  gmsh::model::geo::synchronize();
438  } else {
439  // Nothing
440  }
441 
442  if (ellipsoidPresent == true || enablePeriodicity == false ||
443  cstmDomain == true) {
444  // Nothing
445  } else if (removeBoundaryPacks == true && periodic3D == true) {
446  std::vector<std::pair<int, int>> tagsInsidePacks;
447  gmsh::model::getEntities(tagsInsidePacks, 3);
448  mapPeriodicSurfaces(tagsInsidePacks);
449  } else {
450  std::cout << " - Ensuring periodicity of geometry ..." << std::endl;
452  gmsh::model::occ::synchronize();
453  }
454 }
455 
457  std::cout << " - Writing triangulated surface files ..." << std::endl;
458 
459  std::vector<std::pair<int, int>> tagsPts;
460  gmsh::model::getEntities(tagsPts, 0);
461  if (meshSz != -1) gmsh::model::mesh::setSize(tagsPts, meshSz);
462  gmsh::option::setNumber("Mesh.Algorithm", meshingAlgorithm);
463  gmsh::model::mesh::generate(2);
464  for (int i = 0; i < refineIter; i++) gmsh::model::mesh::refine();
465  gmsh::model::mesh::removeDuplicateNodes();
466 
467  if (OutFile.find(".stl") != std::string::npos)
469  else if (OutFile.find(".vtu") != std::string::npos ||
470  OutFile.find(".vtk") != std::string::npos) {
471  size_t pos = std::string::npos;
472  while ((pos = OutFile.find(".vtu")) != std::string::npos) {
473  OutFile.erase(pos, 4);
474  }
475  while ((pos = OutFile.find(".vtk")) != std::string::npos) {
476  OutFile.erase(pos, 4);
477  }
478  geomToVTK(OutFile + ".msh");
479  } else if (OutFile.find(".msh") != std::string::npos) {
481  } else {
482  gmsh::write(OutFile);
483  }
484 
485  if (defOutputs) {
486  size_t lastindex = OutFile.find_last_of(".");
487  std::string rawname = OutFile.substr(0, lastindex);
488  std::string stlFile = rawname + ".stl";
489  std::string vtkFile = rawname + ".msh";
490  std::string mshFile = rawname + ".msh";
491  geomToSTL(stlFile);
492  geomToMsh(mshFile);
493  geomToVTK(vtkFile);
494  }
495 }
496 
498  // Figure out how to save geometry
499  std::cout << " - Writing Periodic mesh files ..." << std::endl;
500 
501  std::vector<std::pair<int, int>> tagsPts;
502  gmsh::model::getEntities(tagsPts, 0);
503 
504  if (meshSz != -1) gmsh::model::mesh::setSize(tagsPts, meshSz);
505 
507  gmsh::option::setNumber("Mesh.StlOneSolidPerSurface", 2);
508 
509  gmsh::option::setNumber("Mesh.Algorithm3D", meshingAlgorithm);
510  gmsh::option::setNumber("Mesh.SaveGroupsOfNodes", 1);
511  gmsh::model::mesh::generate(3);
512  gmsh::model::mesh::setOrder(elementOrder);
513  for (int i = 0; i < refineIter; i++) gmsh::model::mesh::refine();
514  gmsh::model::mesh::removeDuplicateNodes();
515  double np = 0.0;
516  gmsh::option::getNumber("Mesh.NbNodes", np);
517  nptsMsh = static_cast<int>(np);
518 
519  if (OutFile.find(".stl") != std::string::npos)
521  else if (OutFile.find(".vtu") != std::string::npos ||
522  OutFile.find(".vtk") != std::string::npos) {
523  size_t pos = std::string::npos;
524  while ((pos = OutFile.find(".vtu")) != std::string::npos) {
525  OutFile.erase(pos, 4);
526  }
527  while ((pos = OutFile.find(".vtk")) != std::string::npos) {
528  OutFile.erase(pos, 4);
529  }
530  geomToVTK(OutFile + ".msh");
531  } else if (OutFile.find(".msh") != std::string::npos) {
533  } else {
534  gmsh::write(OutFile);
535  }
536 
537  if ((OutFile.find(".inp") != std::string::npos) && (assignSidePatches))
539 
540  if (defOutputs) {
541  size_t lastindex = OutFile.find_last_of(".");
542  std::string rawname = OutFile.substr(0, lastindex);
543  std::string stlFile = rawname + ".stl";
544  std::string vtkFile = rawname + ".msh";
545  std::string mshFile = rawname + ".msh";
546  geomToSTL(stlFile);
547  geomToMsh(mshFile);
548  geomToVTK(vtkFile);
549  }
550 }
551 
552 // Private methods
553 void rocPack::geomToSTL(const std::string &writeFile) {
554  // Writes created periodic geometries into STL file
555  gmsh::write(writeFile);
556 }
557 
558 void rocPack::geomToVTK(const std::string &writeFile) {
559  // Writes created periodic geometries into VTU file with metadata
560  size_t lastindex = writeFile.find_last_of(".");
561  std::string rawname = writeFile.substr(0, lastindex);
562  rawname = rawname + "_oldMSH.msh";
563  gmsh::option::setNumber("Mesh.MshFileVersion", 2.2);
564  geomToMsh(rawname);
565  meshBase *mb = meshBase::exportGmshToVtk(rawname);
566  nptsMsh = mb->getNumberOfPoints();
567  mb->write(rawname);
568  if (mb) delete mb;
569 }
570 
571 void rocPack::geomToMsh(const std::string &writeFile) {
572  // Writes created periodic geometries into .msh file
573  gmsh::write(writeFile);
574 }
575 
576 void rocPack::makePeriodic(const bool rmbPacks) {
577  if (rmbPacks == false) {
578  /*
579  // To get processor clocktime
580  std::clock_t start;
581  double duration;
582  start = std::clock();
583  */
584 
585  std::vector<double> xTranslate;
586  std::vector<double> yTranslate;
587  std::vector<double> zTranslate;
588 
589  xTranslate.push_back(Xdim); // 0 -> X+
590  yTranslate.push_back(0); // 0 -> X+
591  zTranslate.push_back(0); // 0 -> X+
592  xTranslate.push_back(Xdim); //// 1 -> X+ Z+
593  yTranslate.push_back(0); //// 1 -> X+ Z+
594  zTranslate.push_back(Zdim); //// 1 -> X+ Z+
595  xTranslate.push_back(Xdim); // 2 -> X+ Z-
596  yTranslate.push_back(0); // 2 -> X+ Z-
597  zTranslate.push_back(-Zdim); // 2 -> X+ Z-
598 
599  xTranslate.push_back(-Xdim); // 3 -> X-
600  yTranslate.push_back(0); // 3 -> X-
601  zTranslate.push_back(0); // 3 -> X-
602  xTranslate.push_back(-Xdim); //// 4 -> X- Z+
603  yTranslate.push_back(0); //// 4 -> X- Z+
604  zTranslate.push_back(Zdim); //// 4 -> X- Z+
605  xTranslate.push_back(-Xdim); // 5 -> X- Z-
606  yTranslate.push_back(0); // 5 -> X- Z-
607  zTranslate.push_back(-Zdim); // 5 -> X- Z-
608 
609  xTranslate.push_back(0); // 6 -> Y+
610  yTranslate.push_back(Ydim); // 6 -> Y+
611  zTranslate.push_back(0); // 6 -> Y+
612  xTranslate.push_back(0); //// 7 -> Y+ Z+
613  yTranslate.push_back(Ydim); //// 7 -> Y+ Z+
614  zTranslate.push_back(Zdim); //// 7 -> Y+ Z+
615  xTranslate.push_back(0); // 8 -> Y+ Z-
616  yTranslate.push_back(Ydim); // 8 -> Y+ Z-
617  zTranslate.push_back(-Zdim); // 8 -> Y+ Z-
618 
619  xTranslate.push_back(0); // 9 -> Y-
620  yTranslate.push_back(-Ydim); // 9 -> Y-
621  zTranslate.push_back(0); // 9 -> Y-
622  xTranslate.push_back(0); //// 10 -> Y- Z+
623  yTranslate.push_back(-Ydim); //// 10 -> Y- Z+
624  zTranslate.push_back(Zdim); //// 10 -> Y- Z+
625  xTranslate.push_back(0); // 11 -> Y- Z-
626  yTranslate.push_back(-Ydim); // 11 -> Y- Z-
627  zTranslate.push_back(-Zdim); // 11 -> Y- Z-
628 
629  xTranslate.push_back(Xdim); // 12 -> X+ Y+
630  yTranslate.push_back(Ydim); // 12 -> X+ Y+
631  zTranslate.push_back(0); // 12 -> X+ Y+
632  xTranslate.push_back(Xdim); //// 13 -> X+ Y+ Z+
633  yTranslate.push_back(Ydim); //// 13 -> X+ Y+ Z+
634  zTranslate.push_back(Zdim); //// 13 -> X+ Y+ Z+
635  xTranslate.push_back(Xdim); // 14 -> X+ Y+ Z-
636  yTranslate.push_back(Ydim); // 14 -> X+ Y+ Z-
637  zTranslate.push_back(-Zdim); // 14 -> X+ Y+ Z-
638 
639  xTranslate.push_back(Xdim); // 15 -> X+ Y-
640  yTranslate.push_back(-Ydim); // 15 -> X+ Y-
641  zTranslate.push_back(0); // 15 -> X+ Y-
642  xTranslate.push_back(Xdim); //// 16 -> X+ Y- Z+
643  yTranslate.push_back(-Ydim); //// 16 -> X+ Y- Z+
644  zTranslate.push_back(Zdim); //// 16 -> X+ Y- Z+
645  xTranslate.push_back(Xdim); // 17 -> X+ Y- Z-
646  yTranslate.push_back(-Ydim); // 17 -> X+ Y- Z-
647  zTranslate.push_back(-Zdim); // 17 -> X+ Y- Z-
648 
649  xTranslate.push_back(-Xdim); // 18 -> X- Y+
650  yTranslate.push_back(Ydim); // 18 -> X- Y+
651  zTranslate.push_back(0); // 18 -> X- Y+
652  xTranslate.push_back(-Xdim); //// 19 -> X- Y+ Z+
653  yTranslate.push_back(Ydim); //// 19 -> X- Y+ Z+
654  zTranslate.push_back(Zdim); //// 19 -> X- Y+ Z+
655  xTranslate.push_back(-Xdim); // 20 -> X- Y+ Z-
656  yTranslate.push_back(Ydim); // 20 -> X- Y+ Z-
657  zTranslate.push_back(-Zdim); // 20 -> X- Y+ Z-
658 
659  xTranslate.push_back(-Xdim); // 21 -> X- Y-
660  yTranslate.push_back(-Ydim); // 21 -> X- Y-
661  zTranslate.push_back(0); // 21 -> X- Y-
662  xTranslate.push_back(-Xdim); //// 22 -> X- Y- Z+
663  yTranslate.push_back(-Ydim); //// 22 -> X- Y- Z+
664  zTranslate.push_back(Zdim); //// 22 -> X- Y- Z+
665  xTranslate.push_back(-Xdim); // 23 -> X- Y- Z-
666  yTranslate.push_back(-Ydim); // 23 -> X- Y- Z-
667  zTranslate.push_back(-Zdim); // 23 -> X- Y- Z-
668 
669  xTranslate.push_back(0); // 24 -> Z+
670  yTranslate.push_back(0); // 24 -> Z+
671  zTranslate.push_back(Zdim); // 24 -> Z+
672  xTranslate.push_back(0); //// 25 -> Z-
673  yTranslate.push_back(0); //// 25 -> Z-
674  zTranslate.push_back(-Zdim); //// 25 -> Z-
675 
676  /*// Need some implementation of picking up boundary shapes using get
677  Entities
678  // in bounding box command and translate only those. Aim to get points in a
679  // bounding box and iteratively find parent entity.
680 
681  // If there are less than 25 total volumes, just use the whole tagged
682  // boundary volumes, otherwise use the selected volumes from each side
683  // (left, right, up, etc..)
684 
685  double tol = 0.5;
686  double edgeTol = 0.001;
687  // double Xdim2 = 0;
688  // double Ydim2 = 0;
689  // double Zdim2 = 0;
690 
691  // left
692  std::vector<std::pair<int, int>> entityLeft;
693  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, boxPt[1] - tol,
694  boxPt[2] - tol, boxPt[0] + edgeTol,
695  boxPt[1] + Ydim + tol,
696  Zdim + boxPt[2] + tol, entityLeft,0);
697 
698  // Right
699  std::vector<std::pair<int, int>> entityRight;
700  gmsh::model::getEntitiesInBoundingBox(Xdim + boxPt[0] - edgeTol, boxPt[1] -
701  tol, boxPt[2] - tol, Xdim + boxPt[0] + tol, Ydim + boxPt[1] + tol, Zdim +
702  boxPt[2] + tol, entityRight,0);
703 
704  // Up
705  std::vector<std::pair<int, int>> entityUp;
706  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, Ydim + boxPt[1] -
707  edgeTol, boxPt[2] - tol, Xdim + boxPt[0] + tol, Ydim + boxPt[1] + tol, Zdim +
708  boxPt[2] + tol, entityUp, 0);
709 
710  // Down
711  std::vector<std::pair<int, int>> entityDown;
712  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, boxPt[1] - tol,
713  boxPt[2] - tol, Xdim + boxPt[0] + tol,
714  boxPt[1] + edgeTol, Zdim + boxPt[2] +
715  tol, entityDown, 0);
716 
717  // Back
718  std::vector<std::pair<int, int>> entityBack;
719  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, boxPt[1] - tol,
720  boxPt[2] - tol, Xdim + boxPt[0] + tol,
721  Ydim + boxPt[1] + tol, boxPt[2] +
722  edgeTol, entityBack, 0);
723 
724  //Front
725  std::vector<std::pair<int, int>> entityFront;
726  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, boxPt[1] - tol,
727  Zdim + boxPt[2] - edgeTol,
728  Xdim + boxPt[0] + tol,
729  Ydim + boxPt[1] + tol,
730  Zdim + boxPt[2] + tol,
731  entityFront, 0);
732 
733  // Now start getting parent entities for captured points in other vectors
734  std::vector<std::pair<int,int>> leftShapes;
735  std::vector<std::pair<int,int>> rightShapes;
736  std::vector<std::pair<int,int>> UpShapes;
737  std::vector<std::pair<int,int>> DownShapes;
738  std::vector<std::pair<int,int>> backShapes;
739  std::vector<std::pair<int,int>> frontShapes;
740 
741  for (int i=0; i<bndryPackTags.size(); i++) {
742  std::vector<std::pair<int,int>> tmpTagVec;
743  std::vector<std::pair<int,int>> outPoints;
744  tmpTagVec.push_back(std::make_pair(bndryPackTags[i].first,
745  bndryPackTags[i].second));
746  gmsh::model::getBoundary(tmpTagVec,outPoints,true,true,true);
747 
748  int matchFound = 0;
749 
750  // Left
751  for (int j=0; j<outPoints.size(); j++) {
752  for (int k=0; k<entityLeft.size(); k++) {
753  if (outPoints[j].second == entityLeft[k].second) {
754  matchFound++;
755  break;
756  }
757  }
758  if (matchFound > 0)
759  break;
760  }
761  if (matchFound > 0) {
762  leftShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
763  }
764 
765 
766  // Right
767  matchFound = 0;
768  for (int j=0; j<outPoints.size(); j++) {
769  for (int k=0; k<entityRight.size(); k++) {
770  if (outPoints[j].second == entityRight[k].second) {
771  matchFound++;
772  break;
773  }
774  }
775 
776  if (matchFound > 0)
777  break;
778  }
779 
780  if (matchFound > 0) {
781  rightShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
782  }
783 
784 
785  // Up
786  matchFound = 0;
787  for (int j=0; j<outPoints.size(); j++) {
788  for (int k=0; k<entityUp.size(); k++) {
789  if (outPoints[j].second == entityUp[k].second) {
790  matchFound++;
791  break;
792  }
793  }
794 
795  if (matchFound > 0)
796  break;
797  }
798 
799  if (matchFound > 0) {
800  UpShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
801  }
802 
803 
804  // Down
805  matchFound = 0;
806  for (int j=0; j<outPoints.size(); j++) {
807  for (int k=0; k<entityDown.size(); k++) {
808  if (outPoints[j].second == entityDown[k].second) {
809  matchFound++;
810  break;
811  }
812  }
813 
814  if (matchFound > 0)
815  break;
816  }
817 
818  if (matchFound > 0) {
819  DownShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
820  }
821 
822 
823  // Back
824  matchFound = 0;
825  for (int j=0; j<outPoints.size(); j++) {
826  for (int k=0; k<entityBack.size(); k++) {
827  if (outPoints[j].second == entityBack[k].second) {
828  matchFound++;
829  break;
830  }
831  }
832 
833  if (matchFound > 0)
834  break;
835  }
836 
837  if (matchFound > 0) {
838  backShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
839  }
840 
841 
842  // Front
843  matchFound = 0;
844  for (int j=0; j<outPoints.size(); j++) {
845  for (int k=0; k<entityFront.size(); k++) {
846  if (outPoints[j].second == entityFront[k].second) {
847  matchFound++;
848  break;
849  }
850  }
851 
852  if (matchFound > 0)
853  break;
854  }
855 
856  if (matchFound > 0) {
857  frontShapes.push_back(std::make_pair(3,bndryPackTags[i].second));
858  }
859  }
860 
861  std::ofstream fileInspect;
862  fileInspect.open("Inspect.csv");
863 
864  fileInspect << "Left";
865  for (int i=0; i<leftShapes.size(); i++)
866  fileInspect << "," << leftShapes[i];
867  fileInspect << std::endl;
868 
869  fileInspect << "Right";
870  for (int i=0; i<rightShapes.size(); i++)
871  fileInspect << "," << rightShapes[i];
872  fileInspect << std::endl;
873 
874  fileInspect << "Up";
875  for (int i=0; i<UpShapes.size(); i++)
876  fileInspect << "," << UpShapes[i];
877  fileInspect << std::endl;
878 
879  fileInspect << "Down";
880  for (int i=0; i<DownShapes.size(); i++)
881  fileInspect << "," << DownShapes[i];
882  fileInspect << std::endl;
883 
884  fileInspect << "Back";
885  for (int i=0; i<backShapes.size(); i++)
886  fileInspect << "," << backShapes[i];
887  fileInspect << std::endl;
888 
889  fileInspect << "Front";
890  for (int i=0; i<frontShapes.size(); i++)
891  fileInspect << "," << frontShapes[i];
892  fileInspect << std::endl;
893 
894  fileInspect.close();
895 
896  //gmsh::model::occ::addBox(boxPt[0], boxPt[1], boxPt[2], Xdim, Ydim, Zdim);
897  //gmsh::model::occ::synchronize();
898  //gmsh::fltk::run();
899 
900  // Start Translating
901  std::vector<int> indTra;
902  indTra.resize(6);
903 
904  indTra.push_back(0); indTra.push_back(3); indTra.push_back(6);
905  indTra.push_back(9); indTra.push_back(24); indTra.push_back(25);
906 
907  // Translation is not working, Need to think something.
908 
909  if (leftShapes.size() > 0) {
910  // Left side (X+, X-, Y+, Y-, Z+, Z-)
911  for (int h=0; h<indTra.size(); h++) {
912  std::vector<std::pair<int, int>> tagsCopy;
913  gmsh::model::occ::copy(leftShapes, tagsCopy);
914  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
915  yTranslate[indTra[h]], zTranslate[indTra[h]]);
916  }
917  }
918 
919  if (rightShapes.size() > 0) {
920  // Right Side (X+, X-, Y+, Y-, Z+, Z-)
921  for (int h=0; h<indTra.size(); h++) {
922  std::vector<std::pair<int, int>> tagsCopy;
923  gmsh::model::occ::copy(rightShapes, tagsCopy);
924  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
925  yTranslate[indTra[h]], zTranslate[indTra[h]]);
926  }
927  }
928 
929  if (UpShapes.size() > 0) {
930  // Up (X+, X-, Y+, Y-, Z+, Z-)
931  for (int h=0; h<indTra.size(); h++) {
932  std::vector<std::pair<int, int>> tagsCopy;
933  gmsh::model::occ::copy(UpShapes, tagsCopy);
934  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
935  yTranslate[indTra[h]], zTranslate[indTra[h]]);
936  }
937  }
938 
939  if (DownShapes.size() > 0) {
940  // Down (X+, X-, Y+, Y-, Z+, Z-)
941  for (int h=0; h<indTra.size(); h++) {
942  std::vector<std::pair<int, int>> tagsCopy;
943  gmsh::model::occ::copy(DownShapes, tagsCopy);
944  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
945  yTranslate[indTra[h]], zTranslate[indTra[h]]);
946  }
947  }
948 
949  if (backShapes.size() > 0) {
950  // Back (X+, X-, Y+, Y-, Z+, Z-)
951  for (int h=0; h<indTra.size(); h++) {
952  std::vector<std::pair<int, int>> tagsCopy;
953  gmsh::model::occ::copy(backShapes, tagsCopy);
954  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
955  yTranslate[indTra[h]], zTranslate[indTra[h]]);
956  }
957  }
958 
959  if (frontShapes.size() > 0) {
960  // Front (X+, X-, Y+, Y-, Z+, Z-)
961  for (int h=0; h<indTra.size(); h++) {
962  std::vector<std::pair<int, int>> tagsCopy;
963  gmsh::model::occ::copy(frontShapes, tagsCopy);
964  gmsh::model::occ::translate(tagsCopy, xTranslate[indTra[h]],
965  yTranslate[indTra[h]], zTranslate[indTra[h]]);
966  }
967  }
968  gmsh::model::occ::synchronize();*/
969 
970  // Translating shapes
971  std::vector<int> indexVols;
972  std::vector<int> indexShapes;
973  if (physGrpPerShape) {
974  for (int g = 0; g < bndryPackTags.size(); g++) {
975  std::map<int, int>::iterator itrMp = storeShapeNames.begin();
976  itrMp = storeShapeNames.find(bndryPackTags[g].second);
977 
978  if (itrMp != storeShapeNames.end()) {
979  indexShapes.push_back(itrMp->second);
980  indexVols.push_back(g);
981  }
982  }
983  }
984 
985  std::vector<int> tmpVec;
986  if ((enablePhysGrp) || (internalCohesiveBool)) {
987  linkMultiPhysGrps.resize(26 * bndryPackTags.size() + nameOfPcks.size());
988  for (int i = 0; i < nameOfPcks.size(); i++) {
989  tmpVec.push_back(i + 1);
990  linkMultiPhysGrps[i] = i + 1;
991  }
992  }
993 
994  int ptg = 1;
995  std::cerr << " Progress --> [0%";
996 
997  for (int h = 0; h < 26; h++) {
998  std::vector<std::pair<int, int>> tagsCopy;
999  gmsh::model::occ::copy(bndryPackTags, tagsCopy);
1000  gmsh::model::occ::translate(tagsCopy, xTranslate[h], yTranslate[h],
1001  zTranslate[h]);
1002 
1003  // Links shape type with volume number
1004  if (physGrpPerShape)
1005  for (int g = 0; g < indexVols.size(); g++)
1006  storeShapeNames[tagsCopy[indexVols[g]].second] = indexShapes[g];
1007 
1009  for (int g = 0; g < bndryPackTags.size(); g++)
1010  linkMultiPhysGrps[tagsCopy[g].second - 1] =
1011  tmpVec[bndryPackTags[g].second - 1];
1012 
1013  if (h % 3 == 0) {
1014  std::cerr.precision(3);
1015  std::cerr << ".." << 10.7142857 * (ptg) << "%";
1016  ptg++;
1017  }
1018  }
1019  gmsh::model::occ::synchronize();
1020 
1021  // Containers for boolean operation
1022  std::vector<std::pair<int, int>> tagsPacks;
1023  std::vector<std::pair<int, int>> outBoolean;
1024  std::vector<std::vector<std::pair<int, int>>> outBoolMap;
1025  gmsh::model::getEntities(tagsPacks, 3);
1026  std::vector<std::pair<int, int>> tagsBox;
1027  int tmpTag = gmsh::model::occ::addBox(boxPt[0], boxPt[1], boxPt[2], Xdim,
1028  Ydim, Zdim);
1029  tagsBox.push_back(std::make_pair(3, tmpTag));
1030 
1031  // Boolean Intersection
1032  gmsh::model::occ::intersect(tagsPacks, tagsBox, outBoolean, outBoolMap);
1033  std::cout << "..100%]" << std::endl;
1034 
1035  gmsh::model::occ::synchronize();
1036 
1037  if (physGrpPerShape) {
1038  for (int mp = 0; mp < outBoolean.size(); mp++) {
1039  std::map<int, int>::iterator itrMp = storeShapeNames.begin();
1040 
1041  itrMp = storeShapeNames.find(outBoolean[mp].second);
1042 
1043  if (itrMp != storeShapeNames.end()) {
1044  if (itrMp->second == 0) spherePhysicalGroup.push_back(itrMp->first);
1045  if (itrMp->second == 1)
1046  ellipsoidPhysicalGroup.push_back(itrMp->first);
1047  if (itrMp->second == 2)
1048  cylindersPhysicalGroup.push_back(itrMp->first);
1049  if (itrMp->second == 3) hmxPhysicalGroup.push_back(itrMp->first);
1050  if (itrMp->second == 4) petnPhysicalGroup.push_back(itrMp->first);
1051  if (itrMp->second == 5)
1052  icosidodecahedronPhysicalGroup.push_back(itrMp->first);
1053  }
1054  }
1055  }
1056 
1057  if ((enablePhysGrp) || (internalCohesiveBool)) {
1058  // storeMultiPhysGrps
1059  for (int k = 0; k < tmpVec.size(); k++) {
1060  std::vector<int> oneVols;
1061  for (int j = 0; j < outBoolean.size(); j++) {
1062  if (tmpVec[k] == linkMultiPhysGrps[outBoolean[j].second - 1]) {
1063  oneVols.push_back(outBoolean[j].second);
1064  }
1065  }
1066  storeMultiPhysGrps.push_back(oneVols);
1067  }
1068  }
1069 
1070  if (periodic3D == true) {
1071  std::cout << " - Mapping Periodic Surfaces" << std::endl;
1072  mapPeriodicSurfaces(outBoolean);
1073  }
1074  } else {
1075  // Nothing
1076  }
1077 }
1078 
1079 // Finds particular word in file and returns that line
1080 std::string rocPack::findWord(const std::string &word) {
1081  std::ifstream input(InFile);
1082  std::string line;
1083  while (std::getline(input, line))
1084  if (line.find(word) == 0) return line;
1085  return "";
1086 }
1087 
1088 std::vector<std::string> rocPack::getShapeData(
1089  const int &iter, const std::string &a, const std::vector<std::string> &L) {
1090  std::vector<std::string> LTokens = nemAux::Tokenize(L[iter], a);
1091  return LTokens;
1092 }
1093 
1094 void rocPack::makeSphere(const int &n) {
1095  double sphereRad = 1 * scaleOfPack[n];
1096  int newVol =
1097  gmsh::model::occ::addSphere(translateParams[n][0], translateParams[n][1],
1098  translateParams[n][2], sphereRad);
1099  if (physGrpPerShape) storeShapeNames[newVol] = 0;
1100 
1101  gmsh::model::occ::synchronize();
1102 }
1103 
1104 void rocPack::makeEllipsoid(const int &n) {
1105  std::vector<int> pts;
1106  std::vector<int> arcs;
1107  std::vector<int> loops;
1108  std::vector<int> surfs;
1109  std::vector<int> tmpCurveLoop;
1110  std::vector<std::vector<double>> elVerts;
1111  std::vector<std::vector<double>> rotatedVerts;
1112  elVerts.resize(7);
1113  rotatedVerts.resize(7);
1114  pts.resize(7);
1115  arcs.resize(12);
1116  loops.resize(8);
1117  surfs.resize(8);
1118 
1119  // Scaling vertices
1120  elVerts[0].resize(3);
1121  elVerts[0][0] = 0;
1122  elVerts[0][1] = 0;
1123  elVerts[0][2] = 0;
1124  elVerts[1].resize(3);
1125  elVerts[1][0] = scaleOfPack[n] * ellipsoidRad[0];
1126  elVerts[1][1] = 0;
1127  elVerts[1][2] = 0;
1128  elVerts[2].resize(3);
1129  elVerts[2][0] = 0;
1130  elVerts[2][1] = scaleOfPack[n] * ellipsoidRad[1];
1131  elVerts[2][2] = 0;
1132  elVerts[3].resize(3);
1133  elVerts[3][0] = 0;
1134  elVerts[3][1] = 0;
1135  elVerts[3][2] = scaleOfPack[n] * ellipsoidRad[2];
1136  elVerts[4].resize(3);
1137  elVerts[4][0] = -scaleOfPack[n] * ellipsoidRad[0];
1138  elVerts[4][1] = 0;
1139  elVerts[4][2] = 0;
1140  elVerts[5].resize(3);
1141  elVerts[5][0] = 0;
1142  elVerts[5][1] = -scaleOfPack[n] * ellipsoidRad[1];
1143  elVerts[5][2] = 0;
1144  elVerts[6].resize(3);
1145  elVerts[6][0] = 0;
1146  elVerts[6][1] = 0;
1147  elVerts[6][2] = -scaleOfPack[n] * ellipsoidRad[2];
1148 
1149  // Rotating vertices
1151  for (int i = 0; i < 7; i++)
1152  rotatedVerts[i] = rotateByQuaternion(q, elVerts[i]);
1153 
1154  // Adding translated points
1155 
1156  for (int i = 0; i < rotatedVerts.size(); i++)
1157  pts[i] =
1158  gmsh::model::geo::addPoint(rotatedVerts[i][0] + translateParams[n][0],
1159  rotatedVerts[i][1] + translateParams[n][1],
1160  rotatedVerts[i][2] + translateParams[n][2]);
1161 
1162  // Try circle arc here
1163  arcs[0] = gmsh::model::geo::addEllipseArc(pts[1], pts[0], pts[6], pts[6]);
1164  arcs[1] = gmsh::model::geo::addEllipseArc(pts[6], pts[0], pts[4], pts[4]);
1165  arcs[2] = gmsh::model::geo::addEllipseArc(pts[4], pts[0], pts[3], pts[3]);
1166  arcs[3] = gmsh::model::geo::addEllipseArc(pts[3], pts[0], pts[1], pts[1]);
1167  arcs[4] = gmsh::model::geo::addEllipseArc(pts[1], pts[0], pts[2], pts[2]);
1168  arcs[5] = gmsh::model::geo::addEllipseArc(pts[2], pts[0], pts[4], pts[4]);
1169  arcs[6] = gmsh::model::geo::addEllipseArc(pts[4], pts[0], pts[5], pts[5]);
1170  arcs[7] = gmsh::model::geo::addEllipseArc(pts[5], pts[0], pts[1], pts[1]);
1171  arcs[8] = gmsh::model::geo::addEllipseArc(pts[6], pts[0], pts[2], pts[2]);
1172  arcs[9] = gmsh::model::geo::addEllipseArc(pts[2], pts[0], pts[3], pts[3]);
1173  arcs[10] = gmsh::model::geo::addEllipseArc(pts[3], pts[0], pts[5], pts[5]);
1174  arcs[11] = gmsh::model::geo::addEllipseArc(pts[5], pts[0], pts[6], pts[6]);
1175 
1176  // Adding line loops
1177  tmpCurveLoop.push_back(arcs[4]);
1178  tmpCurveLoop.push_back(arcs[9]);
1179  tmpCurveLoop.push_back(arcs[3]);
1180  loops[0] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1181  tmpCurveLoop.clear();
1182  tmpCurveLoop.push_back(arcs[8]);
1183  tmpCurveLoop.push_back(-arcs[4]);
1184  tmpCurveLoop.push_back(arcs[0]);
1185  loops[1] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1186  tmpCurveLoop.clear();
1187  tmpCurveLoop.push_back(-arcs[9]);
1188  tmpCurveLoop.push_back(arcs[5]);
1189  tmpCurveLoop.push_back(arcs[2]);
1190  loops[2] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1191  tmpCurveLoop.clear();
1192  tmpCurveLoop.push_back(-arcs[5]);
1193  tmpCurveLoop.push_back(-arcs[8]);
1194  tmpCurveLoop.push_back(arcs[1]);
1195  loops[3] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1196  tmpCurveLoop.clear();
1197  tmpCurveLoop.push_back(arcs[7]);
1198  tmpCurveLoop.push_back(-arcs[3]);
1199  tmpCurveLoop.push_back(arcs[10]);
1200  loops[4] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1201  tmpCurveLoop.clear();
1202  tmpCurveLoop.push_back(arcs[11]);
1203  tmpCurveLoop.push_back(-arcs[7]);
1204  tmpCurveLoop.push_back(-arcs[0]);
1205  loops[5] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1206  tmpCurveLoop.clear();
1207  tmpCurveLoop.push_back(-arcs[10]);
1208  tmpCurveLoop.push_back(-arcs[2]);
1209  tmpCurveLoop.push_back(arcs[6]);
1210  loops[6] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1211  tmpCurveLoop.clear();
1212  tmpCurveLoop.push_back(-arcs[1]);
1213  tmpCurveLoop.push_back(-arcs[6]);
1214  tmpCurveLoop.push_back(-arcs[11]);
1215  loops[7] = gmsh::model::geo::addCurveLoop(tmpCurveLoop);
1216  tmpCurveLoop.clear();
1217 
1218  // Adding compound surfaces
1219  tmpCurveLoop.push_back(loops[0]);
1220  surfs[0] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1221  tmpCurveLoop.clear();
1222  tmpCurveLoop.push_back(loops[1]);
1223  surfs[1] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1224  tmpCurveLoop.clear();
1225  tmpCurveLoop.push_back(loops[2]);
1226  surfs[2] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1227  tmpCurveLoop.clear();
1228  tmpCurveLoop.push_back(loops[3]);
1229  surfs[3] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1230  tmpCurveLoop.clear();
1231  tmpCurveLoop.push_back(loops[4]);
1232  surfs[4] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1233  tmpCurveLoop.clear();
1234  tmpCurveLoop.push_back(loops[5]);
1235  surfs[5] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1236  tmpCurveLoop.clear();
1237  tmpCurveLoop.push_back(loops[6]);
1238  surfs[6] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1239  tmpCurveLoop.clear();
1240  tmpCurveLoop.push_back(loops[7]);
1241  surfs[7] = gmsh::model::geo::addSurfaceFilling(tmpCurveLoop);
1242  tmpCurveLoop.clear();
1243 
1244  // Surface loop
1245  tmpCurveLoop.push_back(surfs[0]);
1246  tmpCurveLoop.push_back(surfs[1]);
1247  tmpCurveLoop.push_back(surfs[2]);
1248  tmpCurveLoop.push_back(surfs[3]);
1249  tmpCurveLoop.push_back(surfs[4]);
1250  tmpCurveLoop.push_back(surfs[5]);
1251  tmpCurveLoop.push_back(surfs[6]);
1252  tmpCurveLoop.push_back(surfs[7]);
1253  int surfLoop = gmsh::model::geo::addSurfaceLoop(tmpCurveLoop);
1254  tmpCurveLoop.clear();
1255 
1256  // Volume
1257  tmpCurveLoop.push_back(surfLoop);
1258  int newVol = gmsh::model::geo::addVolume(tmpCurveLoop);
1259  gmsh::model::geo::synchronize();
1260 
1261  if (physGrpPerShape) storeShapeNames[newVol] = 1;
1262 
1263  gmsh::model::geo::synchronize();
1264 }
1265 
1266 void rocPack::makeCylinder(const int &n) {
1267  // "cylParams" is vector with 2 values in shape definition
1268  // cylParams[0] = Radius
1269  // cylParams[1] = Height
1270 
1271  // Scaling everything on thr fly
1272  // Cylinder Center
1273  std::vector<double> cylCenter = std::vector<double>(3);
1274  cylCenter[0] = 0;
1275  cylCenter[1] = 0 - (cylParams[1] / 2) * scaleOfPack[n];
1276  cylCenter[2] = 0;
1277 
1278  // Cylinder Translation Axis
1279  std::vector<double> translation_axis = std::vector<double>(3);
1280  translation_axis[0] = 0;
1281  translation_axis[1] = (cylParams[1]) * scaleOfPack[n];
1282  translation_axis[2] = 0;
1283 
1284  // Cylinder Vertices
1285  std::vector<std::vector<double>> cylVertices;
1286  cylVertices.resize(4);
1287  cylVertices[0].resize(3);
1288  cylVertices[1].resize(3);
1289  cylVertices[2].resize(3);
1290  cylVertices[3].resize(3);
1291 
1292  cylVertices[0][0] = 0;
1293  cylVertices[0][1] = 0 - (cylParams[1] / 2) * scaleOfPack[n];
1294  cylVertices[0][2] = 0 + cylParams[0] * scaleOfPack[n];
1295  cylVertices[1][0] = 0 + cylParams[0] * scaleOfPack[n];
1296  cylVertices[1][1] = 0 - (cylParams[1] / 2) * scaleOfPack[n];
1297  cylVertices[1][2] = 0;
1298  cylVertices[2][0] = 0;
1299  cylVertices[2][1] = 0 - (cylParams[1] / 2) * scaleOfPack[n];
1300  cylVertices[2][2] = 0 - cylParams[0] * scaleOfPack[n];
1301  cylVertices[3][0] = 0 - cylParams[0] * scaleOfPack[n];
1302  cylVertices[3][1] = 0 - (cylParams[1] / 2) * scaleOfPack[n];
1303  cylVertices[3][2] = 0;
1304 
1305  // Rotate By Quaternion
1307 
1308  std::vector<double> rotatedCylCenter;
1309  std::vector<double> rotatedTranslationAxis;
1310  std::vector<std::vector<double>> rotatedCylVertices;
1311  rotatedCylVertices.resize(4);
1312 
1313  // Center
1314  rotatedCylCenter = rotateByQuaternion(q, cylCenter);
1315 
1316  // Translation_Axis
1317  rotatedTranslationAxis = rotateByQuaternion(q, translation_axis);
1318 
1319  // Vertices
1320  for (int i = 0; i < 4; i++)
1321  rotatedCylVertices[i] = rotateByQuaternion(q, cylVertices[i]);
1322 
1323  // Start adding geometry
1324  std::vector<int> pts = std::vector<int>(5);
1325 
1326  pts[0] =
1327  gmsh::model::occ::addPoint(rotatedCylCenter[0] + translateParams[n][0],
1328  rotatedCylCenter[1] + translateParams[n][1],
1329  rotatedCylCenter[2] + translateParams[n][2]);
1330 
1331  for (int i = 0; i < rotatedCylVertices.size(); i++)
1332  pts[i + 1] = gmsh::model::occ::addPoint(
1333  rotatedCylVertices[i][0] + translateParams[n][0],
1334  rotatedCylVertices[i][1] + translateParams[n][1],
1335  rotatedCylVertices[i][2] + translateParams[n][2]);
1336 
1337  std::vector<int> arcs = std::vector<int>(4);
1338  arcs[0] = gmsh::model::occ::addCircleArc(pts[1], pts[0], pts[2]);
1339  arcs[1] = gmsh::model::occ::addCircleArc(pts[2], pts[0], pts[3]);
1340  arcs[2] = gmsh::model::occ::addCircleArc(pts[3], pts[0], pts[4]);
1341  arcs[3] = gmsh::model::occ::addCircleArc(pts[4], pts[0], pts[1]);
1342 
1343  std::vector<int> curves = std::vector<int>(4);
1344  curves[0] = arcs[0];
1345  curves[1] = arcs[1];
1346  curves[2] = arcs[2];
1347  curves[3] = arcs[3];
1348  int loop = gmsh::model::occ::addCurveLoop(curves);
1349 
1350  std::vector<int> loops = std::vector<int>(1);
1351  loops[0] = loop;
1352  int surf = gmsh::model::occ::addPlaneSurface(loops);
1353 
1354  gmsh::model::occ::synchronize();
1355  std::vector<std::pair<int, int>> tagsSurfs;
1356  std::vector<std::pair<int, int>> outVols;
1357  tagsSurfs.push_back(std::make_pair(2, surf));
1358 
1359  gmsh::model::occ::extrude(tagsSurfs, rotatedTranslationAxis[0],
1360  rotatedTranslationAxis[1],
1361  rotatedTranslationAxis[2], outVols);
1362 
1363  for (int i = 0; i < outVols.size(); i++)
1364  if (outVols[i].first == 3)
1365  if (physGrpPerShape) storeShapeNames[outVols[i].second] = 2;
1366 
1367  gmsh::model::occ::synchronize();
1368 }
1369 
1370 void rocPack::makeCrystalShape(const int &n, const int &index) {
1371  std::vector<std::vector<double>> scaledVerts;
1372  scaledVerts.resize(verts[index].size());
1373 
1374  // Scaling Vertices
1375  for (int i = 0; i < verts[index].size(); i++) {
1376  scaledVerts[i].resize(3);
1377  for (int j = 0; j < verts[index][i].size(); j++)
1378  scaledVerts[i][j] = verts[index][i][j] * scaleOfPack[n];
1379  }
1380 
1381  // Rotating Vertices using Quaternions
1383  std::vector<std::vector<double>> rotatedVerts;
1384  rotatedVerts.resize(verts[index].size());
1385 
1386  for (int i = 0; i < verts[index].size(); i++)
1387  rotatedVerts[i] = rotateByQuaternion(q, scaledVerts[i]);
1388 
1389  // Translating Vertices
1390  for (int i = 0; i < rotatedVerts.size(); i++)
1391  for (int j = 0; j < rotatedVerts[i].size(); j++)
1392  rotatedVerts[i][j] = rotatedVerts[i][j] + translateParams[n][j];
1393 
1394  // Creating geometry
1395  std::vector<int> pts;
1396  pts.resize(rotatedVerts.size());
1397  for (int i = 0; i < rotatedVerts.size(); i++) {
1398  pts[i] = gmsh::model::occ::addPoint(rotatedVerts[i][0], rotatedVerts[i][1],
1399  rotatedVerts[i][2]);
1400  }
1401 
1402  std::vector<std::vector<int>> lines;
1403  lines.resize(faces[index].size());
1404  std::vector<int> surfs;
1405  surfs.resize(faces[index].size());
1406  std::vector<int> lineLoops;
1407  lineLoops.resize(faces[index].size());
1408 
1409  std::map<std::pair<int, int>, int> lineMap;
1410  // Adding lines and surfaces
1411  for (int i = 0; i < faces[index].size(); i++) {
1412  lines[i].resize(faces[index][i].size());
1413  for (int j = 0; j < faces[index][i].size(); j++) {
1414  // Finding for existing line
1415  std::map<std::pair<int, int>, int>::iterator it;
1416  int a = pts[faces[index][i][j]];
1417  int b = pts[faces[index][i][(j + 1) % faces[index][i].size()]];
1418 
1419  it = lineMap.find(std::make_pair(a, b));
1420 
1421  if (it == lineMap.end()) it = lineMap.find(std::make_pair(b, a));
1422 
1423  if (it == lineMap.end()) {
1424  lines[i][j] = gmsh::model::occ::addLine(a, b);
1425  lineMap.insert(std::make_pair(std::make_pair(a, b), lines[i][j]));
1426  } else
1427  lines[i][j] = it->second;
1428  }
1429 
1430  // Adding Line Loop
1431  lineLoops[i] = gmsh::model::occ::addCurveLoop(lines[i]);
1432  // Adding Surface
1433  std::vector<int> tagsSurfFill = std::vector<int>(1);
1434  tagsSurfFill[0] = lineLoops[i];
1435  if (nameOfPcks[n] == "icosidodecahedron")
1436  surfs[i] = gmsh::model::occ::addSurfaceFilling(lineLoops[i]);
1437  else
1438  surfs[i] = gmsh::model::occ::addPlaneSurface(tagsSurfFill);
1439  }
1440 
1441  // Adding Surface Loop
1442  int surfLoop = gmsh::model::occ::addSurfaceLoop(surfs);
1443 
1444  // Adding Volumes
1445  std::vector<int> surfLoopTags = std::vector<int>(1);
1446  surfLoopTags[0] = surfLoop;
1447  int newVol = gmsh::model::occ::addVolume(surfLoopTags);
1448 
1449  if (physGrpPerShape) {
1450  if (nameOfPcks[n] == "hmx") storeShapeNames[newVol] = 3;
1451 
1452  if (nameOfPcks[n] == "petn") storeShapeNames[newVol] = 4;
1453 
1454  if (nameOfPcks[n] == "icosidodecahedron") storeShapeNames[newVol] = 5;
1455  }
1456 
1457  gmsh::model::occ::synchronize();
1458 }
1459 
1461  // Normalize
1462  for (int k = 0; k < verts.size(); k++) {
1463  double maxNorm = 0.0;
1464  for (int i = 0; i < verts[k].size(); i++) {
1465  double norm = sqrt(pow(verts[k][i][0], 2) + pow(verts[k][i][1], 2) +
1466  pow(verts[k][i][2], 2));
1467  if (norm > maxNorm) maxNorm = norm;
1468  }
1469 
1470  for (int i = 0; i < verts[k].size(); i++) {
1471  verts[k][i][0] = (verts[k][i][0] / maxNorm);
1472  verts[k][i][1] = (verts[k][i][1] / maxNorm);
1473  verts[k][i][2] = (verts[k][i][2] / maxNorm);
1474  }
1475  }
1476 }
1477 
1479  // Add method for removing boundary packs
1480  std::vector<std::pair<int, int>> tagsWithinBoundary;
1481  std::vector<std::pair<int, int>> tagsAll;
1482 
1483  std::vector<int> insidePacks;
1484  std::vector<int> allPacks;
1485  std::vector<int> bndryPackVols;
1486 
1487  gmsh::model::getEntitiesInBoundingBox(boxPt[0], boxPt[1], boxPt[2],
1488  boxPt[0] + Xdim, boxPt[1] + Ydim,
1489  boxPt[2] + Zdim, tagsWithinBoundary, 3);
1490 
1491  gmsh::model::getEntities(tagsAll, 3);
1492 
1493  for (auto iter : tagsWithinBoundary) insidePacks.push_back(iter.second);
1494 
1495  for (auto iter2 : tagsAll) allPacks.push_back(iter2.second);
1496 
1497  for (int i = 0; i < allPacks.size(); i++) {
1498  int ht = 0;
1499  for (int j = 0; j < insidePacks.size(); j++)
1500  if (allPacks[i] == insidePacks[j]) {
1501  ht++;
1502  break;
1503  }
1504 
1505  if (ht == 0) bndryPackVols.push_back(allPacks[i]);
1506  }
1507 
1508  if ((tagsWithinBoundary.size() == 0 && sntChk) && (removeBoundaryPacks)) {
1509  if (just2Physgrps) {
1510  std::cerr << "There are no volumes left inside the Box!" << std::endl;
1511  std::cerr << "Try increasing the domain size or pack density!"
1512  << std::endl;
1513  std::cerr << "Or disable physical group options" << std::endl;
1514  throw;
1515  }
1516  }
1517 
1518  // Converting volumes into pair
1519  for (int i = 0; i < bndryPackVols.size(); i++)
1520  bndryPackTags.push_back(std::make_pair(3, bndryPackVols[i]));
1521 }
1522 
1523 std::vector<double> rocPack::rotateByQuaternion(const rocQuaternion &q,
1524  const std::vector<double> &v) {
1525  Eigen::VectorXd InputVec(3);
1526  Eigen::VectorXd RotatedVec(3);
1527  std::vector<double> returnVec = std::vector<double>(3);
1528 
1529  InputVec[0] = v[0];
1530  InputVec[1] = v[1];
1531  InputVec[2] = v[2];
1532 
1533  Eigen::Quaternion<double> Quaternion(q.w, q.x, q.y, q.z);
1534 
1535  RotatedVec = Quaternion._transformVector(InputVec);
1536 
1537  returnVec[0] = RotatedVec[0];
1538  returnVec[1] = RotatedVec[1];
1539  returnVec[2] = RotatedVec[2];
1540 
1541  return returnVec;
1542 }
1543 
1544 rocQuaternion rocPack::toQuaternion(const std::vector<double> &r) {
1545  rocQuaternion q; // Declaring Quaternion
1546  double angle = r[3] * 3.141592653589 / 180; // Declaring Angle in Radians
1547 
1548  q.x = r[0] * sin(angle / 2);
1549  q.y = r[1] * sin(angle / 2);
1550  q.z = r[2] * sin(angle / 2);
1551  q.w = cos(angle / 2);
1552 
1553  return q;
1554 }
1555 
1557  const std::vector<std::pair<int, int>> &prevTags) {
1558  // Boolean Fragment
1559  gmsh::model::occ::synchronize();
1560  std::vector<std::pair<int, int>> tagsBox2;
1561  int tmpTag2 =
1562  gmsh::model::occ::addBox(boxPt[0], boxPt[1], boxPt[2], Xdim, Ydim, Zdim);
1563  tagsBox2.push_back(std::make_pair(3, tmpTag2));
1564  std::vector<std::pair<int, int>> outBoolean2;
1565  std::vector<std::vector<std::pair<int, int>>> outBoolMap2;
1566  gmsh::model::occ::fragment(tagsBox2, prevTags, outBoolean2, outBoolMap2);
1567  gmsh::model::occ::synchronize();
1568 
1569  if (assignSidePatches) {
1570  // Get boundaries of box
1571  std::vector<std::pair<int, int>> tagstmpVOL;
1572  tagstmpVOL.push_back(std::make_pair(3, tmpTag2));
1573  std::vector<std::pair<int, int>> tagsAllsurfs;
1574 
1575  gmsh::model::getBoundary(tagstmpVOL, tagsAllsurfs);
1576 
1577  int totalSurfsinBox = tagsAllsurfs.size() - 1;
1578 
1579  // Last 6 surfaces
1580  std::vector<int> surfTagUp;
1581  surfTagUp.push_back(tagsAllsurfs[totalSurfsinBox - 2].second);
1582  int Up = gmsh::model::addPhysicalGroup(2, surfTagUp);
1583  gmsh::model::setPhysicalName(2, Up, "Up");
1584 
1585  std::vector<int> surfTagDown;
1586  surfTagDown.push_back(tagsAllsurfs[totalSurfsinBox - 4].second);
1587  int Down = gmsh::model::addPhysicalGroup(2, surfTagDown);
1588  gmsh::model::setPhysicalName(2, Down, "Down");
1589 
1590  std::vector<int> surfTagLeft;
1591  surfTagLeft.push_back(tagsAllsurfs[totalSurfsinBox - 5].second);
1592  int Left = gmsh::model::addPhysicalGroup(2, surfTagLeft);
1593  gmsh::model::setPhysicalName(2, Left, "Left");
1594 
1595  std::vector<int> surfTagRight;
1596  surfTagRight.push_back(tagsAllsurfs[totalSurfsinBox].second);
1597  int Right = gmsh::model::addPhysicalGroup(2, surfTagRight);
1598  gmsh::model::setPhysicalName(2, Right, "Right");
1599 
1600  std::vector<int> surfTagFront;
1601  surfTagFront.push_back(tagsAllsurfs[totalSurfsinBox - 3].second);
1602  int Front = gmsh::model::addPhysicalGroup(2, surfTagFront);
1603  gmsh::model::setPhysicalName(2, Front, "Front");
1604 
1605  std::vector<int> surfTagBack;
1606  surfTagBack.push_back(tagsAllsurfs[totalSurfsinBox - 1].second);
1607  int Back = gmsh::model::addPhysicalGroup(2, surfTagBack);
1608  gmsh::model::setPhysicalName(2, Back, "Back");
1609  }
1610 
1611  if (((enablePhysGrp) && (just2Physgrps)) ||
1612  ((enablePhysGrp) && (physGrpPerShape)) ||
1613  ((just2Physgrps) && (physGrpPerShape))) {
1614  std::cerr << "Please select only one option for physical group"
1615  << std::endl;
1616  throw;
1617  }
1618 
1619  if (enablePhysGrp) {
1620  // Creating Physical Groups
1621  // Same volume on both periodic boundaries needs to be same physical group
1622  std::vector<int> vecTags;
1623  vecTags.push_back(tmpTag2);
1624  surroundingGrp = gmsh::model::addPhysicalGroup(3, vecTags);
1625  gmsh::model::setPhysicalName(3, surroundingGrp, "Surrounding");
1626 
1627  for (int i = 0; i < storeMultiPhysGrps.size(); i++) {
1628  std::vector<int> newTags;
1629  std::string name = "Vol" + std::to_string(i);
1630 
1631  for (int j = 0; j < storeMultiPhysGrps[i].size(); j++)
1632  newTags.push_back(storeMultiPhysGrps[i][j]);
1633 
1634  int newGrp = gmsh::model::addPhysicalGroup(3, newTags);
1635  multiGrpIndices.push_back(newGrp);
1636  gmsh::model::setPhysicalName(3, newGrp, name);
1637  }
1638  } else if (just2Physgrps) {
1639  // Creating Physical Groups
1640  std::vector<int> vecTags;
1641  vecTags.push_back(tmpTag2);
1642  surroundingGrp = gmsh::model::addPhysicalGroup(3, vecTags);
1643  gmsh::model::setPhysicalName(3, surroundingGrp, "Surrounding");
1644 
1645  std::vector<std::pair<int, int>> tagsAll;
1646  gmsh::model::getEntities(tagsAll, 3);
1647  std::vector<int> newTags;
1648 
1649  for (int i = 0; i < tagsAll.size(); i++) {
1650  if (tagsAll[i].second == tmpTag2) {
1651  } else {
1652  newTags.push_back(tagsAll[i].second);
1653  }
1654  }
1655 
1656  packGrp = gmsh::model::addPhysicalGroup(3, newTags);
1657  gmsh::model::setPhysicalName(3, packGrp, "MicroStructures");
1658  } else if (physGrpPerShape) {
1659  // Defining Physical Groups Per Shape
1660  std::vector<int> vecTags;
1661  vecTags.push_back(tmpTag2);
1662  surroundingGrp = gmsh::model::addPhysicalGroup(3, vecTags);
1663  gmsh::model::setPhysicalName(3, surroundingGrp, "Surrounding");
1664 
1665  // Spheres
1666  if (spherePhysicalGroup.size() > 0) {
1667  int newGrp = gmsh::model::addPhysicalGroup(3, spherePhysicalGroup);
1668  multiGrpIndices.push_back(newGrp);
1669  gmsh::model::setPhysicalName(3, newGrp, "Spheres");
1670  }
1671 
1672  // Cylinders
1673  if (cylindersPhysicalGroup.size() > 0) {
1674  int newGrp = gmsh::model::addPhysicalGroup(3, cylindersPhysicalGroup);
1675  multiGrpIndices.push_back(newGrp);
1676  gmsh::model::setPhysicalName(3, newGrp, "Cylinders");
1677  }
1678 
1679  // Ellipsoids
1680  if (ellipsoidPhysicalGroup.size() > 0) {
1681  int newGrp = gmsh::model::addPhysicalGroup(3, ellipsoidPhysicalGroup);
1682  multiGrpIndices.push_back(newGrp);
1683  gmsh::model::setPhysicalName(3, newGrp, "Ellipsoids");
1684  }
1685 
1686  // PETN
1687  if (petnPhysicalGroup.size() > 0) {
1688  int newGrp = gmsh::model::addPhysicalGroup(3, petnPhysicalGroup);
1689  multiGrpIndices.push_back(newGrp);
1690  gmsh::model::setPhysicalName(3, newGrp, "PETN");
1691  }
1692 
1693  // Icosidodecahedron
1694  if (icosidodecahedronPhysicalGroup.size() > 0) {
1695  int newGrp =
1696  gmsh::model::addPhysicalGroup(3, icosidodecahedronPhysicalGroup);
1697  multiGrpIndices.push_back(newGrp);
1698  gmsh::model::setPhysicalName(3, newGrp, "Icosidodecahedron");
1699  }
1700 
1701  // HMX
1702  if (hmxPhysicalGroup.size() > 0) {
1703  int newGrp = gmsh::model::addPhysicalGroup(3, hmxPhysicalGroup);
1704  multiGrpIndices.push_back(newGrp);
1705  gmsh::model::setPhysicalName(3, newGrp, "HMX");
1706  }
1707 
1708  } else {
1709  surroundingGrp = tmpTag2;
1710 
1711  std::vector<std::pair<int, int>> tagsAll;
1712  gmsh::model::getEntities(tagsAll, 3);
1713 
1714  for (int i = 0; i < tagsAll.size(); i++) {
1715  if (tagsAll[i].second == tmpTag2) {
1716  } else {
1717  multiGrpIndices.push_back(tagsAll[i].second);
1718  }
1719  }
1720  }
1721 
1722  // Finding surfaces at each side
1723  double tol = 0.001;
1724 
1725  // Left
1726  std::vector<std::pair<int, int>> entityLeft;
1727  gmsh::model::getEntitiesInBoundingBox(
1728  boxPt[0] - tol, boxPt[1] - tol, boxPt[2] - tol, boxPt[0] + tol,
1729  boxPt[1] + Ydim + tol, Zdim + boxPt[2] + tol, entityLeft, 2);
1730 
1731  // Right
1732  std::vector<std::pair<int, int>> entityRight;
1733  gmsh::model::getEntitiesInBoundingBox(Xdim + boxPt[0] - tol, boxPt[1] - tol,
1734  boxPt[2] - tol, Xdim + boxPt[0] + tol,
1735  Ydim + boxPt[1] + tol,
1736  Zdim + boxPt[2] + tol, entityRight, 2);
1737 
1738  // Up
1739  std::vector<std::pair<int, int>> entityUp;
1740  gmsh::model::getEntitiesInBoundingBox(boxPt[0] - tol, Ydim + boxPt[1] - tol,
1741  boxPt[2] - tol, Xdim + boxPt[0] + tol,
1742  Ydim + boxPt[1] + tol,
1743  Zdim + boxPt[2] + tol, entityUp, 2);
1744 
1745  // Down
1746  std::vector<std::pair<int, int>> entityDown;
1747  gmsh::model::getEntitiesInBoundingBox(
1748  boxPt[0] - tol, boxPt[1] - tol, boxPt[2] - tol, Xdim + boxPt[0] + tol,
1749  boxPt[1] + tol, Zdim + boxPt[2] + tol, entityDown, 2);
1750 
1751  // Back
1752  std::vector<std::pair<int, int>> entityBack;
1753  gmsh::model::getEntitiesInBoundingBox(
1754  boxPt[0] - tol, boxPt[1] - tol, boxPt[2] - tol, Xdim + boxPt[0] + tol,
1755  Ydim + boxPt[1] + tol, boxPt[2] + tol, entityBack, 2);
1756 
1757  // Front
1758  std::vector<std::pair<int, int>> entityFront;
1759  gmsh::model::getEntitiesInBoundingBox(
1760  boxPt[0] - tol, boxPt[1] - tol, Zdim + boxPt[2] - tol,
1761  Xdim + boxPt[0] + tol, Ydim + boxPt[1] + tol, Zdim + boxPt[2] + tol,
1762  entityFront, 2);
1763 
1764  // Getting points of individual surfaces
1765  std::vector<std::vector<std::pair<int, int>>> vertsLeft =
1766  getAllPoints(entityLeft);
1767  std::vector<std::vector<std::pair<int, int>>> vertsRight =
1768  getAllPoints(entityRight);
1769  std::vector<std::vector<std::pair<int, int>>> vertsUp =
1770  getAllPoints(entityUp);
1771  std::vector<std::vector<std::pair<int, int>>> vertsDown =
1772  getAllPoints(entityDown);
1773  std::vector<std::vector<std::pair<int, int>>> vertsFront =
1774  getAllPoints(entityFront);
1775  std::vector<std::vector<std::pair<int, int>>> vertsBack =
1776  getAllPoints(entityBack);
1777 
1778  // Getting Periodic Surfaces
1779  std::vector<std::pair<int, int>> periodicSurfsX;
1780  std::vector<std::pair<int, int>> periodicSurfsY;
1781  std::vector<std::pair<int, int>> periodicSurfsZ;
1782 
1783  periodicSurfsX = getPeriodicSurfs(vertsLeft, vertsRight, 0, Xdim);
1784  periodicSurfsY = getPeriodicSurfs(vertsDown, vertsUp, 1, Ydim);
1785  periodicSurfsZ = getPeriodicSurfs(vertsBack, vertsFront, 2, Zdim);
1786 
1787  // Enforcing Periodicity in GMSH model
1788  for (int i = 0; i < periodicSurfsX.size(); i++) {
1789  slaveX.push_back(periodicSurfsX[i].first);
1790  MasterX.push_back(periodicSurfsX[i].second);
1791  }
1792 
1793  for (int i = 0; i < periodicSurfsY.size(); i++) {
1794  slaveY.push_back(periodicSurfsY[i].first);
1795  MasterY.push_back(periodicSurfsY[i].second);
1796  }
1797 
1798  for (int i = 0; i < periodicSurfsZ.size(); i++) {
1799  slaveZ.push_back(periodicSurfsZ[i].first);
1800  MasterZ.push_back(periodicSurfsZ[i].second);
1801  }
1802 
1803  std::vector<std::vector<double>> affineTransform;
1804  affineTransform.resize(3);
1805  affineTransform[0].resize(16); // X
1806  affineTransform[1].resize(16); // Y
1807  affineTransform[2].resize(16); // Z
1808  double xT = -1 * Xdim;
1809  double yT = -1 * Ydim;
1810  double zT = -1 * Zdim;
1811 
1812  affineTransform[0][0] = 1;
1813  affineTransform[0][1] = 0;
1814  affineTransform[0][2] = 0;
1815  affineTransform[0][3] = xT;
1816  affineTransform[0][4] = 0;
1817  affineTransform[0][5] = 1;
1818  affineTransform[0][6] = 0;
1819  affineTransform[0][7] = 0;
1820  affineTransform[0][8] = 0;
1821  affineTransform[0][9] = 0;
1822  affineTransform[0][10] = 1;
1823  affineTransform[0][11] = 0;
1824  affineTransform[0][12] = 0;
1825  affineTransform[0][13] = 0;
1826  affineTransform[0][14] = 0;
1827  affineTransform[0][15] = 1;
1828 
1829  affineTransform[1][0] = 1;
1830  affineTransform[1][1] = 0;
1831  affineTransform[1][2] = 0;
1832  affineTransform[1][3] = 0;
1833  affineTransform[1][4] = 0;
1834  affineTransform[1][5] = 1;
1835  affineTransform[1][6] = 0;
1836  affineTransform[1][7] = yT;
1837  affineTransform[1][8] = 0;
1838  affineTransform[1][9] = 0;
1839  affineTransform[1][10] = 1;
1840  affineTransform[1][11] = 0;
1841  affineTransform[1][12] = 0;
1842  affineTransform[1][13] = 0;
1843  affineTransform[1][14] = 0;
1844  affineTransform[1][15] = 1;
1845 
1846  affineTransform[2][0] = 1;
1847  affineTransform[2][1] = 0;
1848  affineTransform[2][2] = 0;
1849  affineTransform[2][3] = 0;
1850  affineTransform[2][4] = 0;
1851  affineTransform[2][5] = 1;
1852  affineTransform[2][6] = 0;
1853  affineTransform[2][7] = 0;
1854  affineTransform[2][8] = 0;
1855  affineTransform[2][9] = 0;
1856  affineTransform[2][10] = 1;
1857  affineTransform[2][11] = zT;
1858  affineTransform[2][12] = 0;
1859  affineTransform[2][13] = 0;
1860  affineTransform[2][14] = 0;
1861  affineTransform[2][15] = 1;
1862 
1863  gmsh::model::mesh::setPeriodic(2, slaveX, MasterX, affineTransform[0]);
1864  gmsh::model::mesh::setPeriodic(2, slaveY, MasterY, affineTransform[1]);
1865  gmsh::model::mesh::setPeriodic(2, slaveZ, MasterZ, affineTransform[2]);
1866  gmsh::model::occ::synchronize();
1867 }
1868 
1869 std::vector<std::vector<std::pair<int, int>>> rocPack::getAllPoints(
1870  std::vector<std::pair<int, int>> surfaces) {
1871  std::vector<std::vector<std::pair<int, int>>> verts;
1872  verts.resize(surfaces.size());
1873  for (int j = 0; j < surfaces.size(); j++) {
1874  std::vector<std::pair<int, int>> inputTags;
1875  std::vector<std::pair<int, int>> outTags;
1876  inputTags.push_back(std::make_pair(2, surfaces[j].second));
1877 
1878  gmsh::model::getBoundary(inputTags, outTags, true, true, true);
1879  verts[j].resize(outTags.size());
1880  for (int i = 0; i < outTags.size(); i++)
1881  verts[j][i] = std::make_pair(surfaces[j].second, outTags[i].second);
1882  }
1883 
1884  return verts;
1885 }
1886 
1887 std::vector<std::pair<int, int>> rocPack::getPeriodicSurfs(
1888  const std::vector<std::vector<std::pair<int, int>>> &vertsOneSide,
1889  const std::vector<std::vector<std::pair<int, int>>> &vertsOtherSide,
1890  const int &indexTranslate, const double &amountTranslate) {
1891  // Comparing vertices and mapping periodic surfaces
1892  std::vector<double> paramCoords;
1893  std::vector<std::vector<double>> pointsOneSide;
1894  std::vector<std::pair<int, int>> periodicSurfs;
1895 
1896  for (int i = 0; i < vertsOneSide.size(); i++) {
1897  pointsOneSide.resize(vertsOneSide[i].size());
1898 
1899  for (int s = 0; s < vertsOneSide[i].size(); s++) {
1900  gmsh::model::getValue(0, vertsOneSide[i][s].second, paramCoords,
1901  pointsOneSide[s]);
1902  pointsOneSide[s][indexTranslate] =
1903  pointsOneSide[s][indexTranslate] + amountTranslate;
1904  }
1905 
1906  for (int j = 0; j < vertsOtherSide.size(); j++) {
1907  int know = 0;
1908  for (int l = 0; l < vertsOtherSide[j].size(); l++) {
1909  std::vector<double> pointsOtherSide;
1910  gmsh::model::getValue(0, vertsOtherSide[j][l].second, paramCoords,
1911  pointsOtherSide);
1912 
1913  for (int g = 0; g < pointsOneSide.size(); g++) {
1914  double a = pointsOtherSide[0] - pointsOneSide[g][0];
1915  double b = pointsOtherSide[1] - pointsOneSide[g][1];
1916  double c = pointsOtherSide[2] - pointsOneSide[g][2];
1917 
1918  if (std::sqrt(a * a) < 1e-10 &&
1919  pointsOneSide.size() == vertsOtherSide[j].size())
1920  if (std::sqrt(b * b) < 1e-10 &&
1921  pointsOneSide.size() == vertsOtherSide[j].size())
1922  if (std::sqrt(c * c) < 1e-10 &&
1923  pointsOneSide.size() == vertsOtherSide[j].size())
1924  know++;
1925  }
1926  }
1927  if (know == pointsOneSide.size())
1928  periodicSurfs.push_back(std::make_pair(vertsOneSide[i][0].first,
1929  vertsOtherSide[j][0].first));
1930  }
1931  }
1932  return periodicSurfs;
1933 }
1934 
1937 
1938  // Change this method to write periodic equations.
1939  std::cout << " - Writing periodic equation file" << std::endl;
1940 
1941  // Getting all volumes
1942  std::vector<std::pair<int, int>> allVolumes;
1943  gmsh::model::getEntities(allVolumes, 3);
1944 
1945  // Creating pairs of <Volume,Surface> for node mapping
1946  std::vector<std::pair<int, int>> volSurfLinksX;
1947  std::vector<std::pair<int, int>> volSurfLinksY;
1948  std::vector<std::pair<int, int>> volSurfLinksZ;
1949 
1950  // A map for linking master surfaces with corrosponding volumes
1951  // <Surface, Volume>
1952  std::map<int, int> masterLinksX;
1953  std::map<int, int> masterLinksY;
1954  std::map<int, int> masterLinksZ;
1955 
1956  // Linking surfaces with volumes
1957  for (int i = 0; i < allVolumes.size(); i++) {
1958  std::vector<std::pair<int, int>> inputTags;
1959  std::vector<std::pair<int, int>> outTags;
1960  inputTags.push_back(std::make_pair(3, allVolumes[i].second));
1961 
1962  gmsh::model::getBoundary(inputTags, outTags, true, true, false);
1963 
1964  for (int j = 0; j < slaveX.size(); j++)
1965  for (int jj = 0; jj < outTags.size(); jj++)
1966  if (outTags[jj].first == 2 && outTags[jj].second == slaveX[j])
1967  volSurfLinksX.push_back(
1968  std::make_pair(allVolumes[i].second, slaveX[j]));
1969 
1970  for (int k = 0; k < slaveY.size(); k++)
1971  for (int kk = 0; kk < outTags.size(); kk++)
1972  if (outTags[kk].first == 2 && outTags[kk].second == slaveY[k])
1973  volSurfLinksY.push_back(
1974  std::make_pair(allVolumes[i].second, slaveY[k]));
1975 
1976  for (int l = 0; l < slaveZ.size(); l++)
1977  for (int ll = 0; ll < outTags.size(); ll++)
1978  if (outTags[ll].first == 2 && outTags[ll].second == slaveZ[l])
1979  volSurfLinksZ.push_back(
1980  std::make_pair(allVolumes[i].second, slaveZ[l]));
1981 
1982  for (int j = 0; j < MasterX.size(); j++)
1983  for (int jj = 0; jj < outTags.size(); jj++)
1984  if (outTags[jj].first == 2 && outTags[jj].second == MasterX[j])
1985  masterLinksX.insert(std::make_pair(MasterX[j], allVolumes[i].second));
1986 
1987  for (int k = 0; k < MasterY.size(); k++)
1988  for (int kk = 0; kk < outTags.size(); kk++)
1989  if (outTags[kk].first == 2 && outTags[kk].second == MasterY[k])
1990  masterLinksY.insert(std::make_pair(MasterY[k], allVolumes[i].second));
1991 
1992  for (int l = 0; l < MasterZ.size(); l++)
1993  for (int ll = 0; ll < outTags.size(); ll++)
1994  if (outTags[ll].first == 2 && outTags[ll].second == MasterZ[l])
1995  masterLinksZ.insert(std::make_pair(MasterZ[l], allVolumes[i].second));
1996  }
1997 
1998  // Gathering node data
1999 
2000  // Writing periodic.equ file (TODO: Do not include n0,nx,ny,nz as pairs in
2001  // equations)
2002  std::vector<int> doNotRepeat;
2003  for (int i = 0; i < nptsMsh; i++) doNotRepeat.push_back(0);
2004 
2005  std::ofstream periodicEquation;
2006  periodicEquation.open("periodic.equ");
2007  periodicEquation << "**set definitions" << std::endl;
2008  periodicEquation << "*nset, nset=n0" << std::endl;
2009  periodicEquation << eqRefNodes[0] << std::endl;
2010  periodicEquation << "*nset, nset=nx" << std::endl;
2011  periodicEquation << eqRefNodes[1] << std::endl;
2012  periodicEquation << "*nset, nset=ny" << std::endl;
2013  periodicEquation << eqRefNodes[2] << std::endl;
2014  periodicEquation << "*nset, nset=nz" << std::endl;
2015  periodicEquation << eqRefNodes[3] << std::endl;
2016  periodicEquation << "*equation" << std::endl;
2017 
2018  // X Direction (Master(Right) -> Slave(Left))
2019  int forSurfTestX = randomSurfTest * volSurfLinksX.size() / 100;
2020  int forSurfTestY = randomSurfTest * volSurfLinksY.size() / 100;
2021  int forSurfTestZ = randomSurfTest * volSurfLinksZ.size() / 100;
2022  for (int srf = 0; srf < volSurfLinksX.size(); srf++) {
2023  int masterSurfTag;
2024  std::vector<std::size_t> slaveNodes;
2025  std::vector<std::size_t> masterNodes;
2026  std::vector<double> affineTransformData;
2027  gmsh::model::mesh::getPeriodicNodes(2, volSurfLinksX[srf].second,
2028  masterSurfTag, slaveNodes, masterNodes,
2029  affineTransformData);
2030 
2031  /*
2032  int volSlave = volSurfLinksX[srf].first;
2033  int surfSlave = volSurfLinksX[srf].second;
2034 
2035  auto mapIterator = masterLinksX.find(masterSurfTag);
2036  int volMaster = mapIterator->second;
2037  int surfMaster = masterSurfTag;
2038  */
2039 
2040  if (srf == forSurfTestX && masterNodes.size() != 0) {
2041  int indReturn = randomNodeX * masterNodes.size() / 100;
2042  std::vector<double> Mcoords;
2043  std::vector<double> Scoords;
2044  std::vector<double> paramCoords;
2045 
2046  gmsh::model::mesh::getNode(masterNodes[indReturn], Mcoords, paramCoords);
2047  gmsh::model::mesh::getNode(slaveNodes[indReturn], Scoords, paramCoords);
2048 
2049  if ((std::sqrt(Mcoords[0] * Mcoords[0]) -
2050  std::sqrt(Scoords[0] * Scoords[0])) < 1e-05)
2051  if ((std::sqrt(Mcoords[1] * Mcoords[1]) -
2052  std::sqrt(Scoords[1] * Scoords[1])) < 1e-05)
2053  if ((std::sqrt(Mcoords[2] * Mcoords[2]) -
2054  std::sqrt(Scoords[2] * Scoords[2])) < 1e-05)
2055  matchingCoordsX = true;
2056  }
2057 
2058  // Check slave nodes for any interface nodes and if found, add duplicate
2059  // node spawned from that interface node and link against a duplicate node
2060  // spawned from its opposite interface node.
2061  std::vector<int> newMasterNodes;
2062  std::vector<int> newSlaveNodes;
2063  if (internalCohesiveBool) {
2064  for (int i = 0; i < masterNodes.size(); i++) {
2065  if (slaveInterfaceId[masterNodes[i] - 1] == 1) {
2066  newMasterNodes.push_back(ptsReplacer[masterNodes[i] - 1]);
2067  newSlaveNodes.push_back(ptsReplacer[slaveNodes[i] - 1]);
2068  }
2069  }
2070  for (int i = 0; i < newMasterNodes.size(); i++) {
2071  masterNodes.push_back(newMasterNodes[i]);
2072  slaveNodes.push_back(newSlaveNodes[i]);
2073  }
2074  }
2075 
2076  for (int i = 0; i < masterNodes.size(); i++) {
2077  if ((slaveNodes[i] != eqRefNodes[0]) &&
2078  (slaveNodes[i] != eqRefNodes[1]) &&
2079  (slaveNodes[i] != eqRefNodes[2]) &&
2080  (slaveNodes[i] != eqRefNodes[3])) {
2081  if (doNotRepeat[slaveNodes[i] - 1] == 1) {
2082  // Nothing
2083  } else {
2084  doNotRepeat[slaveNodes[i] - 1] = 1;
2085  periodicEquation << "3" << std::endl;
2086  periodicEquation << slaveNodes[i] << ",1,-1," << masterNodes[i]
2087  << ",1,1," << eqRefNodes[1] << ",1,1" << std::endl;
2088 
2089  periodicEquation << "3" << std::endl;
2090  periodicEquation << slaveNodes[i] << ",2,-1," << masterNodes[i]
2091  << ",2,1," << eqRefNodes[1] << ",2,1" << std::endl;
2092 
2093  periodicEquation << "3" << std::endl;
2094  periodicEquation << slaveNodes[i] << ",3,-1," << masterNodes[i]
2095  << ",3,1," << eqRefNodes[1] << ",3,1" << std::endl;
2096  }
2097  }
2098  }
2099  }
2100 
2101  // Y Direction (Master(Up) -> Slave(Down))
2102  for (int srf = 0; srf < volSurfLinksY.size(); srf++) {
2103  int masterSurfTag;
2104  std::vector<std::size_t> slaveNodes;
2105  std::vector<std::size_t> masterNodes;
2106  std::vector<double> affineTransformData;
2107  gmsh::model::mesh::getPeriodicNodes(2, volSurfLinksY[srf].second,
2108  masterSurfTag, slaveNodes, masterNodes,
2109  affineTransformData);
2110 
2111  /*
2112  int volSlave = volSurfLinksY[srf].first;
2113  int surfSlave = volSurfLinksY[srf].second;
2114 
2115  auto mapIterator = masterLinksY.find(masterSurfTag);
2116  int volMaster = mapIterator->second;
2117  int surfMaster = masterSurfTag;
2118  */
2119 
2120  if (srf == forSurfTestY && masterNodes.size() != 0) {
2121  int indReturn = randomNodeY * masterNodes.size() / 100;
2122  std::vector<double> Mcoords;
2123  std::vector<double> Scoords;
2124  std::vector<double> paramCoords;
2125 
2126  gmsh::model::mesh::getNode(masterNodes[indReturn], Mcoords, paramCoords);
2127  gmsh::model::mesh::getNode(slaveNodes[indReturn], Scoords, paramCoords);
2128 
2129  if ((std::sqrt(Mcoords[0] * Mcoords[0]) -
2130  std::sqrt(Scoords[0] * Scoords[0])) < 1e-05)
2131  if ((std::sqrt(Mcoords[1] * Mcoords[1]) -
2132  std::sqrt(Scoords[1] * Scoords[1])) < 1e-05)
2133  if ((std::sqrt(Mcoords[2] * Mcoords[2]) -
2134  std::sqrt(Scoords[2] * Scoords[2])) < 1e-05)
2135  matchingCoordsY = true;
2136  }
2137 
2138  // Check slave nodes for any interface nodes and if found, add duplicate
2139  // node spawned from that interface node and link against a duplicate node
2140  // spawned from its opposite interface node.
2141  std::vector<int> newMasterNodes;
2142  std::vector<int> newSlaveNodes;
2143  if (internalCohesiveBool) {
2144  for (int i = 0; i < masterNodes.size(); i++) {
2145  if (slaveInterfaceId[masterNodes[i] - 1] == 1) {
2146  newMasterNodes.push_back(ptsReplacer[masterNodes[i] - 1]);
2147  newSlaveNodes.push_back(ptsReplacer[slaveNodes[i] - 1]);
2148  }
2149  }
2150 
2151  for (int i = 0; i < newMasterNodes.size(); i++) {
2152  masterNodes.push_back(newMasterNodes[i]);
2153  slaveNodes.push_back(newSlaveNodes[i]);
2154  }
2155  }
2156 
2157  for (int i = 0; i < masterNodes.size(); i++) {
2158  if ((slaveNodes[i] != eqRefNodes[0]) &&
2159  (slaveNodes[i] != eqRefNodes[1]) &&
2160  (slaveNodes[i] != eqRefNodes[2]) &&
2161  (slaveNodes[i] != eqRefNodes[3])) {
2162  if (doNotRepeat[slaveNodes[i] - 1] == 1) {
2163  // Nothing
2164  } else {
2165  doNotRepeat[slaveNodes[i] - 1] = 1;
2166  periodicEquation << "3" << std::endl;
2167  periodicEquation << slaveNodes[i] << ",1,-1," << masterNodes[i]
2168  << ",1,1," << eqRefNodes[2] << ",1,1" << std::endl;
2169 
2170  periodicEquation << "3" << std::endl;
2171  periodicEquation << slaveNodes[i] << ",2,-1," << masterNodes[i]
2172  << ",2,1," << eqRefNodes[2] << ",2,1" << std::endl;
2173 
2174  periodicEquation << "3" << std::endl;
2175  periodicEquation << slaveNodes[i] << ",3,-1," << masterNodes[i]
2176  << ",3,1," << eqRefNodes[2] << ",3,1" << std::endl;
2177  }
2178  }
2179  }
2180  }
2181 
2182  // Z Direction (Master(Front) -> Slave(Back))
2183  for (int srf = 0; srf < volSurfLinksZ.size(); srf++) {
2184  int masterSurfTag;
2185  std::vector<std::size_t> slaveNodes;
2186  std::vector<std::size_t> masterNodes;
2187  std::vector<double> affineTransformData;
2188  gmsh::model::mesh::getPeriodicNodes(2, volSurfLinksZ[srf].second,
2189  masterSurfTag, slaveNodes, masterNodes,
2190  affineTransformData);
2191 
2192  /*
2193  int volSlave = volSurfLinksZ[srf].first;
2194  int surfSlave = volSurfLinksZ[srf].second;
2195 
2196  auto mapIterator = masterLinksZ.find(masterSurfTag);
2197  int volMaster = mapIterator->second;
2198  int surfMaster = masterSurfTag;
2199  */
2200 
2201  if (srf == forSurfTestZ && masterNodes.size() != 0) {
2202  int indReturn = randomNodeZ * masterNodes.size() / 100;
2203  std::vector<double> Mcoords;
2204  std::vector<double> Scoords;
2205  std::vector<double> paramCoords;
2206 
2207  gmsh::model::mesh::getNode(masterNodes[indReturn], Mcoords, paramCoords);
2208  gmsh::model::mesh::getNode(slaveNodes[indReturn], Scoords, paramCoords);
2209 
2210  if ((std::sqrt(Mcoords[0] * Mcoords[0]) -
2211  std::sqrt(Scoords[0] * Scoords[0])) < 1e-05)
2212  if ((std::sqrt(Mcoords[1] * Mcoords[1]) -
2213  std::sqrt(Scoords[1] * Scoords[1])) < 1e-05)
2214  if ((std::sqrt(Mcoords[2] * Mcoords[2]) -
2215  std::sqrt(Scoords[2] * Scoords[2])) < 1e-05)
2216  matchingCoordsZ = true;
2217  }
2218 
2219  // Check slave nodes for any interface nodes and if found, add duplicate
2220  // node spawned from that interface node and link against a duplicate node
2221  // spawned from its opposite interface node.
2222  std::vector<int> newMasterNodes;
2223  std::vector<int> newSlaveNodes;
2224  if (internalCohesiveBool) {
2225  for (int i = 0; i < masterNodes.size(); i++) {
2226  if (slaveInterfaceId[masterNodes[i] - 1] == 1) {
2227  newMasterNodes.push_back(ptsReplacer[masterNodes[i] - 1]);
2228  newSlaveNodes.push_back(ptsReplacer[slaveNodes[i] - 1]);
2229  }
2230  }
2231 
2232  for (int i = 0; i < newMasterNodes.size(); i++) {
2233  masterNodes.push_back(newMasterNodes[i]);
2234  slaveNodes.push_back(newSlaveNodes[i]);
2235  }
2236  }
2237 
2238  for (int i = 0; i < masterNodes.size(); i++) {
2239  if ((slaveNodes[i] != eqRefNodes[0]) &&
2240  (slaveNodes[i] != eqRefNodes[1]) &&
2241  (slaveNodes[i] != eqRefNodes[2]) &&
2242  (slaveNodes[i] != eqRefNodes[3])) {
2243  if (doNotRepeat[slaveNodes[i] - 1] == 1) {
2244  } else {
2245  doNotRepeat[slaveNodes[i] - 1] = 1;
2246  periodicEquation << "3" << std::endl;
2247  periodicEquation << slaveNodes[i] << ",1,-1," << masterNodes[i]
2248  << ",1,1," << eqRefNodes[3] << ",1,1" << std::endl;
2249 
2250  periodicEquation << "3" << std::endl;
2251  periodicEquation << slaveNodes[i] << ",2,-1," << masterNodes[i]
2252  << ",2,1," << eqRefNodes[3] << ",2,1" << std::endl;
2253 
2254  periodicEquation << "3" << std::endl;
2255  periodicEquation << slaveNodes[i] << ",3,-1," << masterNodes[i]
2256  << ",3,1," << eqRefNodes[3] << ",3,1" << std::endl;
2257  }
2258  }
2259  }
2260  }
2261  periodicEquation.close();
2262 }
2263 
2264 void rocPack::setNodeLocations(const int &x, const int &y, const int &z) {
2265  randomNodeX = x;
2266  randomNodeY = y;
2267  randomNodeZ = z;
2268 }
2269 
2270 void rocPack::setRandomSurface(const int &surf) { randomSurfTest = surf; }
2271 
2274  return true;
2275  else
2276  return false;
2277 }
2278 
2279 void rocPack::scaleVols(const int &vol, const int &index) {
2280  std::vector<std::pair<int, int>> tagsIndividual;
2281  tagsIndividual.push_back(std::make_pair(3, vol));
2282  gmsh::model::occ::dilate(tagsIndividual, translateParams[index][0],
2283  translateParams[index][1], translateParams[index][2],
2285 }
2286 
2288  std::vector<std::pair<int, int>> tagsSurfs;
2289  gmsh::model::getEntities(tagsSurfs, 2);
2290 
2291  for (int i = 0; i < tagsSurfs.size(); i++) {
2292  gmsh::model::mesh::setSmoothing(tagsSurfs[i].first, tagsSurfs[i].second,
2293  smoothingIter);
2294  }
2295  gmsh::model::occ::synchronize();
2296 }
2297 
2298 void rocPack::createCohesiveElements(const std::string &filename,
2299  const std::string &outname) {
2300  // Pre-processing to get some important data
2301  if ((sntChk) && (just2Physgrps)) {
2302  gmsh::model::mesh::getNodesForPhysicalGroup(3, surroundingGrp, surrNodeTags,
2303  surrCoords);
2304  gmsh::model::mesh::getNodesForPhysicalGroup(3, packGrp, geomsNodeTags,
2305  geomsCoords);
2306  } else if ((sntChk) && (enablePhysGrp)) {
2307  gmsh::model::mesh::getNodesForPhysicalGroup(3, surroundingGrp, surrNodeTags,
2308  surrCoords);
2309 
2310  for (int i = 0; i < multiGrpIndices.size(); i++) {
2311  std::vector<std::size_t> tmpNodeTags;
2312  gmsh::model::mesh::getNodesForPhysicalGroup(3, multiGrpIndices[i],
2313  tmpNodeTags, geomsCoords);
2314  for (int j = 0; j < tmpNodeTags.size(); j++)
2315  geomsNodeTags.push_back(tmpNodeTags[j]);
2316  }
2317  } else if ((sntChk) && (physGrpPerShape)) {
2318  gmsh::model::mesh::getNodesForPhysicalGroup(3, surroundingGrp, surrNodeTags,
2319  surrCoords);
2320 
2321  for (int i = 0; i < multiGrpIndices.size(); i++) {
2322  std::vector<std::size_t> tmpNodeTags;
2323  gmsh::model::mesh::getNodesForPhysicalGroup(3, multiGrpIndices[i],
2324  tmpNodeTags, geomsCoords);
2325 
2326  for (int j = 0; j < tmpNodeTags.size(); j++)
2327  geomsNodeTags.push_back(tmpNodeTags[j]);
2328  }
2329  } else if (((sntChk) && !(enablePhysGrp)) &&
2330  ((sntChk) && !(physGrpPerShape)) &&
2331  ((sntChk) && !(just2Physgrps))) {
2332  std::vector<double> noUse;
2333  gmsh::model::mesh::getNodes(surrNodeTags, surrCoords, noUse, 3,
2334  surroundingGrp, true, false);
2335 
2336  for (int i = 0; i < multiGrpIndices.size(); i++) {
2337  std::vector<std::size_t> tmpNodes;
2338  gmsh::model::mesh::getNodes(tmpNodes, geomsCoords, noUse, 3,
2339  multiGrpIndices[i], true, false);
2340 
2341  for (int j = 0; j < tmpNodes.size(); j++)
2342  geomsNodeTags.push_back(tmpNodes[j]);
2343  }
2344 
2345  for (int k = 0; k < multiGrpIndices.size(); k++) {
2346  // Getting element tags in surrounding -> surrElementIds
2347  std::vector<int> elementTypes;
2348  std::vector<std::vector<std::size_t>> elementTags;
2349  std::vector<std::vector<std::size_t>> nodeTags;
2350 
2351  gmsh::model::mesh::getElements(elementTypes, elementTags, nodeTags, 3,
2352  multiGrpIndices[k]);
2353 
2354  for (int i = 0; i < elementTags.size(); i++)
2355  for (int j = 0; j < elementTags[i].size(); j++)
2356  geomElementIds.push_back(elementTags[0][j]);
2357  }
2358  } else {
2359  // Nothing
2360  }
2361 
2362  // Reading in mesh file
2363  size_t lastindex = filename.find_last_of(".");
2364  std::string rawname = filename.substr(0, lastindex);
2365  rawname = rawname + "_oldMSH.msh";
2366  meshBase *mb = meshBase::Create(rawname);
2367 
2368  // Changing output name for cohesive elements
2369  size_t lastindex2 = outname.find_last_of(".");
2370  std::string rawname2 = outname.substr(0, lastindex2);
2371  rawname2 = rawname2 + "_withCohesive.vtu";
2372 
2373  // Creating vtk data set for mesh
2374  vtkSmartPointer<vtkDataSet> dataSetSurr;
2375  dataSetSurr = mb->getDataSet();
2376 
2377  int numCells = dataSetSurr->GetNumberOfCells();
2378  int numPoints = dataSetSurr->GetNumberOfPoints();
2379 
2380  // Material assignment vector here
2381  for (int i = 0; i < numPoints; i++) ptsCohesiveGrp.push_back(-1);
2382 
2383  // storeMultiPhysGrps is vector of vectors, storing volumes in each group
2384  int countParts = 100;
2385  for (int i = 0; i < storeMultiPhysGrps.size(); i++) {
2386  std::vector<std::size_t> storeNodes;
2387  for (int j = 0; j < storeMultiPhysGrps[i].size(); j++) {
2388  std::vector<std::size_t> getNodeTags;
2389  std::vector<double> notUseful;
2390  std::vector<double> notUseful2;
2391  gmsh::model::mesh::getNodes(getNodeTags, notUseful, notUseful2, 3,
2392  storeMultiPhysGrps[i][j], true, false);
2393 
2394  for (int k = 0; k < getNodeTags.size(); k++)
2395  storeNodes.push_back(getNodeTags[k]);
2396  }
2397 
2398  for (int j = 0; j < storeNodes.size(); j++) {
2399  // if (ptsCohesiveGrp[storeNodes[j]-1] != -1) {
2400  // std::cerr << "Exception at material assignement" << std::endl;
2401  // throw;
2402  //} else {
2403  ptsCohesiveGrp[storeNodes[j] - 1] = countParts;
2404  //}
2405  }
2406  countParts++;
2407  }
2408 
2409  // Fatching physical groups information
2410  std::vector<double> grpIds(mb->getNumberOfCells(), surroundingGrp);
2411  if ((just2Physgrps) || (enablePhysGrp) || (physGrpPerShape)) {
2412  mb->getCellDataArray("PhysGrpId", grpIds);
2413  } else {
2414  for (int i = 0; i < geomElementIds.size(); i++) grpIds[i] = 2;
2415  }
2416 
2417  std::vector<int> newPtIds;
2418 
2419  // Transfer old dataset to new one with new points
2420  vtkSmartPointer<vtkUnstructuredGrid> dataSetCohesive =
2422 
2423  vtkSmartPointer<vtkUnstructuredGrid> dataSetViz =
2425 
2426  vtkSmartPointer<vtkPoints> pointsViz = vtkSmartPointer<vtkPoints>::New();
2427 
2428  // Provides means of identifying if the node at given index is new duplicate.
2429  std::vector<int> ptsInterfaceID;
2430  // Replaces duplicate nodes at their indexes with their surrounding
2431  // counterparts
2432  std::vector<int> traceBackToSurr;
2433  // new vector
2434  std::vector<int> identifyInterfaceNodes;
2435 
2436  for (int i = 0; i < numPoints; i++) {
2437  std::vector<double> getPt = std::vector<double>(3);
2438  dataSetSurr->GetPoint(i, &getPt[0]);
2439  pointsViz->InsertNextPoint(getPt[0], getPt[1], getPt[2]);
2440  identifyInterfaceNodes.push_back(0);
2441  ptsReplacer.push_back(i);
2442  ptsInterfaceID.push_back(0);
2443  traceBackToSurr.push_back(i);
2444  slaveInterfaceId.push_back(0);
2445  }
2446 
2447  std::clock_t start;
2448  double duration;
2449  start = std::clock();
2450 
2451  // A faster method for finding interface nodes (0.031592 Seconds vs 813
2452  // Seconds for 61782 nodes)
2453  for (int i = 0; i < surrNodeTags.size(); i++)
2454  identifyInterfaceNodes[surrNodeTags[i] - 1] = 1;
2455 
2456  for (int i = 0; i < geomsNodeTags.size(); i++) {
2457  if (identifyInterfaceNodes[geomsNodeTags[i] - 1] == 1) {
2458  interfaceNodes.push_back(geomsNodeTags[i] - 1);
2459  std::vector<double> getPt = std::vector<double>(3);
2460  dataSetSurr->GetPoint(geomsNodeTags[i] - 1, &getPt[0]);
2461  int newP = pointsViz->InsertNextPoint(getPt[0], getPt[1], getPt[2]);
2462  newPtIds.push_back(newP);
2463  ptsReplacer[geomsNodeTags[i] - 1] = newP;
2464  traceBackToSurr.push_back(geomsNodeTags[i] - 1);
2465  slaveInterfaceId[geomsNodeTags[i] - 1] = 1;
2466  }
2467  }
2468 
2469  duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
2470  std::cout << "Process Finished!" << std::endl;
2471  std::cout << "Total " << interfaceNodes.size() << " Nodes duplicated in "
2472  << duration << " seconds!" << std::endl;
2473 
2474  dataSetCohesive->SetPoints(pointsViz);
2475  dataSetViz->SetPoints(pointsViz);
2476 
2477  for (int i = 0; i < interfaceNodes.size(); i++)
2478  ptsInterfaceID.push_back(1); // Updating points identification vector
2479 
2480  // Once we have interface nodes and duplicated the nodes, Surrounding side
2481  // of surface cells needs to be replaced by new nodes.
2482  // Find all cells containing interface nodes and rule out those in physical
2483  // group surrounding.
2484  std::vector<int> cellIdentification;
2485 
2486  // Initialize with zero
2487  for (int i = 0; i < numCells; i++) cellIdentification.push_back(0);
2488 
2489  // Finding all cells in microstructure group that atleast contains one
2490  // interface node.
2491  std::vector<int> pickCells;
2492  for (int i = 0; i < interfaceNodes.size(); i++) {
2493  vtkIdList *cells = vtkIdList::New();
2494  dataSetSurr->GetPointCells(interfaceNodes[i], cells);
2495  for (int j = 0; j < cells->GetNumberOfIds(); j++) {
2496  if (grpIds[cells->GetId(j)] != surroundingGrp) {
2497  cellIdentification[cells->GetId(j)] = 1;
2498  pickCells.push_back(cells->GetId(j));
2499  }
2500  }
2501  }
2502  sort(pickCells.begin(), pickCells.end());
2503  pickCells.erase(unique(pickCells.begin(), pickCells.end()), pickCells.end());
2504 
2505  // Now selected cells contain anywhere between 1 to 3 intefaceNodes that will
2506  // need replacement.
2507  // Make a mesh and keep everything same but replace interface
2508  // nodes with duplicate nodes when the selected cells are encountered.
2509  for (int i = 0; i < numCells; i++) {
2510  vtkCell *cell;
2511  // vtkPoints *fp;
2512  if (cellIdentification[i] == 1) {
2513  cell = dataSetSurr->GetCell(i);
2514  vtkIdList *pts = cell->GetPointIds();
2515  std::vector<int> ptForCells;
2516  ptForCells.resize(4);
2517  for (int j = 0; j < 4; j++) ptForCells[j] = ptsReplacer[pts->GetId(j)];
2518  createVtkCell(dataSetCohesive, 10, ptForCells);
2519  } else {
2520  cell = dataSetSurr->GetCell(i);
2521  vtkIdList *pts = cell->GetPointIds();
2522  std::vector<int> ptForCells;
2523  ptForCells.resize(4);
2524  for (int j = 0; j < 4; j++) ptForCells[j] = pts->GetId(j);
2525  createVtkCell(dataSetCohesive, 10, ptForCells);
2526  }
2527  }
2528 
2529  // Mesh separated successfully!
2530  // Finding out interface faces within picked cells to reveal node order.
2531  std::vector<int> seqNodeMap;
2532  std::vector<int> cellFinal;
2533  std::vector<int> cellsNotPicked;
2534  // int numOfCohElm = 0;
2535 
2536  for (int i = 0; i < pickCells.size(); i++) {
2537  vtkCell *cell;
2538  cell = dataSetCohesive->GetCell(pickCells[i]);
2539  vtkIdList *pts = cell->GetPointIds();
2540  vtkCell3D *cell3d = static_cast<vtkCell3D *>(cell);
2541 
2542  // int atleastOne = 0;
2543  // Looping through all faces of current cell
2544  for (int j = 0; j < 4; j++) {
2545  std::vector<int> tmpSeqStore;
2546  int *ptFaces = nullptr;
2547  cell3d->GetFacePoints(j, ptFaces);
2548  for (int k = 0; k < 3; k++)
2549  if (ptsInterfaceID[pts->GetId(ptFaces[k])] == 1)
2550  tmpSeqStore.push_back(pts->GetId(ptFaces[k]));
2551 
2552  if (tmpSeqStore.size() == 3)
2553  for (int n = 0; n < 3; n++) seqNodeMap.push_back(tmpSeqStore[n]);
2554  }
2555  }
2556 
2557  // Update the material group array here.
2558  std::vector<double> groupId;
2559  for (int i = 0; i < grpIds.size(); i++) groupId.push_back(grpIds[i]);
2560 
2561  // Create cohesive elements
2562  int add = 0;
2563  for (int i = 0; i < (seqNodeMap.size() / 3); i++) {
2564  std::vector<int> ptForCells;
2565  ptForCells.resize(6);
2566  for (int j = 0; j < 3; j++) {
2567  ptForCells[j] = seqNodeMap[j + add];
2568  ptForCells[j + 3] = traceBackToSurr[seqNodeMap[j + add]];
2569  }
2570 
2571  // Search for periodic cohesive elements (existing on periodic boundaries)
2572  std::vector<double> getPt1 = std::vector<double>(3);
2573  std::vector<double> getPt2 = std::vector<double>(3);
2574  std::vector<double> getPt3 = std::vector<double>(3);
2575  dataSetCohesive->GetPoint(ptForCells[0], &getPt1[0]);
2576  dataSetCohesive->GetPoint(ptForCells[1], &getPt2[0]);
2577  dataSetCohesive->GetPoint(ptForCells[2], &getPt3[0]);
2578  if (existsOnPeriodicBoundary(getPt1, getPt2, getPt3)) {
2579  // Do not create that element
2580  } else {
2581  if (ptsCohesiveGrp[ptForCells[3]] == ptsCohesiveGrp[ptForCells[4]])
2582  if (ptsCohesiveGrp[ptForCells[4]] == ptsCohesiveGrp[ptForCells[5]])
2583  if (ptsCohesiveGrp[ptForCells[3]] == ptsCohesiveGrp[ptForCells[5]])
2584  groupId.push_back(ptsCohesiveGrp[ptForCells[3]]);
2585 
2586  createVtkCell(dataSetViz, 13, ptForCells);
2587  createVtkCell(dataSetCohesive, 13, ptForCells);
2588  }
2589  add = add + 3;
2590  }
2591 
2592  /*// Write cohesive elements in gmsh mesh (in development)
2593  std::vector<int> elementTypes;
2594  elementTypes.push_back(6);
2595  std::vector<std::vector<std::size_t>> elementTags;
2596  elementTags.resize(1);
2597  std::vector<std::vector<std::size_t>> nodeTags;
2598  nodeTags.resize(1);
2599 
2600  int add2 = 0;
2601  for (int i = 0; i < (seqNodeMap.size()/3); i++) {
2602  std::vector<int> ptForCells;
2603  ptForCells.resize(6);
2604  for (int j = 0; j < 3 ; j++) {
2605  ptForCells[j] = seqNodeMap[j+add2];
2606  ptForCells[j+3] = traceBackToSurr[seqNodeMap[j+add2]];
2607  }
2608 
2609  elementTags[0].push_back(numCells+i+1);
2610 
2611  for (int j=0; j<6; j++)
2612  nodeTags[0].push_back(ptForCells[j]+1);
2613  add2 = add2 + 3;
2614  }
2615 
2616  gmsh::model::mesh::addElements(3,surroundingGrp,elementTypes,elementTags,nodeTags);
2617 
2618  gmsh::write("GMSH_WITH_COHESIVE.msh");*/
2619 
2620  if (groupId.size() != dataSetCohesive->GetNumberOfCells()) {
2621  std::cerr << "Exception at group id vector size" << std::endl;
2622  throw;
2623  }
2624 
2625  vtkMesh *vm = new vtkMesh(dataSetViz, "CohesiveElements.vtu");
2626  vm->report();
2627  vm->write();
2628 
2629  vtkMesh *vm2 = new vtkMesh(dataSetCohesive, rawname2);
2630  vm2->setCellDataArray("PhysGrpId", groupId);
2631  vm2->report();
2632  vm2->write();
2633 }
2634 
2635 void rocPack::createVtkCell(vtkSmartPointer<vtkUnstructuredGrid> dataSet,
2636  const int cellType, std::vector<int> &vrtIds) {
2637  vtkSmartPointer<vtkIdList> vtkCellIds = vtkSmartPointer<vtkIdList>::New();
2638  vtkCellIds->SetNumberOfIds(vrtIds.size());
2639  for (auto pit = vrtIds.begin(); pit != vrtIds.end(); pit++)
2640  vtkCellIds->SetId(pit - vrtIds.begin(), *pit);
2641  dataSet->InsertNextCell(cellType, vtkCellIds);
2642 }
2643 
2644 void rocPack::translateAll(const double &X, const double &Y, const double &Z) {
2645  xUDF = X;
2646  yUDF = Y;
2647  zUDF = Z;
2648 }
2649 
2650 void rocPack::setCustomDomain(const std::vector<double> &domainBounds) {
2651  cstmDomain = true;
2652 
2653  boxPt.clear();
2654  boxPt.resize(3);
2655 
2656  boxPt[0] = domainBounds[0] + xUDF;
2657  boxPt[1] = domainBounds[1] + yUDF;
2658  boxPt[2] = domainBounds[2] + zUDF;
2659 
2660  Xdim = domainBounds[3];
2661  Ydim = domainBounds[4];
2662  Zdim = domainBounds[5];
2663 }
2664 
2665 void rocPack::setMeshingAlgorithm(const int &mshAlg) {
2666  meshingAlgorithm = mshAlg;
2667 }
2668 
2670 
2671 void rocPack::sanityCheckOn() { sntChk = true; }
2672 
2674 
2676  std::size_t cellTag;
2677  int cellType = 0;
2678  std::vector<std::size_t> nodeIds;
2679  double u, v, w;
2680  int elemDim = -1;
2681 
2682  gmsh::model::mesh::getElementByCoordinates(boxPt[0], boxPt[1], boxPt[2],
2683  cellTag, cellType, nodeIds, u, v,
2684  w, elemDim, true);
2685 
2686  for (int i = 0; i < nodeIds.size(); i++) {
2687  std::vector<double> coords;
2688  std::vector<double> paramCoords;
2689 
2690  gmsh::model::mesh::getNode(nodeIds[i], coords, paramCoords);
2691 
2692  if (coords[0] == boxPt[0])
2693  if (coords[1] == boxPt[1])
2694  if (coords[2] == boxPt[2]) eqRefNodes[0] = nodeIds[i];
2695  }
2696 
2697  nodeIds.clear();
2698 
2699  gmsh::model::mesh::getElementByCoordinates(boxPt[0] + Xdim, boxPt[1],
2700  boxPt[2], cellTag, cellType,
2701  nodeIds, u, v, w, elemDim, true);
2702 
2703  for (int i = 0; i < nodeIds.size(); i++) {
2704  std::vector<double> coords;
2705  std::vector<double> paramCoords;
2706 
2707  gmsh::model::mesh::getNode(nodeIds[i], coords, paramCoords);
2708 
2709  if (coords[0] == boxPt[0] + Xdim) {
2710  if (coords[1] == boxPt[1]) {
2711  if (coords[2] == boxPt[2]) {
2712  eqRefNodes[1] = nodeIds[i];
2713  break;
2714  }
2715  }
2716  }
2717  }
2718  nodeIds.clear();
2719 
2720  gmsh::model::mesh::getElementByCoordinates(boxPt[0], boxPt[1] + Ydim,
2721  boxPt[2], cellTag, cellType,
2722  nodeIds, u, v, w, elemDim, true);
2723  for (int i = 0; i < nodeIds.size(); i++) {
2724  std::vector<double> coords;
2725  std::vector<double> paramCoords;
2726 
2727  gmsh::model::mesh::getNode(nodeIds[i], coords, paramCoords);
2728 
2729  if (coords[0] == boxPt[0]) {
2730  if (coords[1] == boxPt[1] + Ydim) {
2731  if (coords[2] == boxPt[2]) {
2732  eqRefNodes[2] = nodeIds[i];
2733  break;
2734  }
2735  }
2736  }
2737  }
2738  nodeIds.clear();
2739 
2740  gmsh::model::mesh::getElementByCoordinates(boxPt[1], boxPt[2],
2741  boxPt[2] + Zdim, cellTag, cellType,
2742  nodeIds, u, v, w, elemDim, true);
2743  for (int i = 0; i < nodeIds.size(); i++) {
2744  std::vector<double> coords;
2745  std::vector<double> paramCoords;
2746 
2747  gmsh::model::mesh::getNode(nodeIds[i], coords, paramCoords);
2748 
2749  if (coords[0] == boxPt[0]) {
2750  if (coords[1] == boxPt[1]) {
2751  if (coords[2] == boxPt[2] + Zdim) {
2752  eqRefNodes[3] = nodeIds[i];
2753  break;
2754  }
2755  }
2756  }
2757  }
2758  nodeIds.clear();
2759 }
2760 
2761 bool rocPack::existsOnPeriodicBoundary(const std::vector<double> &getPt1,
2762  const std::vector<double> &getPt2,
2763  const std::vector<double> &getPt3) {
2764  // Check if all 3 points exist on any of these 6 surfaces
2765  // 1. X = boxPt[0]
2766  if ((getPt1[0] == boxPt[0]) && (getPt2[0] == boxPt[0]) &&
2767  (getPt3[0] == boxPt[0]))
2768  return true;
2769  // 2. X = boxPt[0] + Xdim
2770  else if ((getPt1[0] == boxPt[0] + Xdim) && (getPt2[0] == boxPt[0] + Xdim) &&
2771  (getPt3[0] == boxPt[0] + Xdim))
2772  return true;
2773  // 3. Y = boxPt[1]
2774  else if ((getPt1[1] == boxPt[1]) && (getPt2[1] == boxPt[1]) &&
2775  (getPt3[1] == boxPt[1]))
2776  return true;
2777  // 4. Y = boxPt[1] + Ydim
2778  else if ((getPt1[1] == boxPt[1] + Ydim) && (getPt2[1] == boxPt[1] + Ydim) &&
2779  (getPt3[1] == boxPt[1] + Ydim))
2780  return true;
2781  // 5. Z = boxPt[2]
2782  else if ((getPt1[2] == boxPt[2]) && (getPt2[2] == boxPt[2]) &&
2783  (getPt3[2] == boxPt[2]))
2784  return true;
2785  // 6. Z = boxPt[2] + Zdim
2786  else if ((getPt1[2] == boxPt[2] + Zdim) && (getPt2[2] == boxPt[2] + Zdim) &&
2787  (getPt3[2] == boxPt[2] + Zdim))
2788  return true;
2789  else
2790  return false;
2791 }
2792 
2793 void rocPack::modifyInpMesh(const std::string &modifyFile) {
2794  size_t lastindex = modifyFile.find_last_of(".");
2795  std::string rawname = modifyFile.substr(0, lastindex);
2796  std::string fname = rawname + ".inp";
2797  std::vector<std::string> fileLines;
2798  std::ifstream meshFile(fname);
2799  if (meshFile.is_open()) {
2800  // Get all lines from current file
2801  std::string linesOut;
2802  while (std::getline(meshFile, linesOut)) fileLines.push_back(linesOut);
2803 
2804  int start = 0;
2805  int end = 0;
2806  for (int i = 0; i < fileLines.size(); i++) {
2807  if (fileLines[i].find("*ELEMENT, type=CPS3, ELSET=") == 0) {
2808  start = i;
2809  break;
2810  }
2811  }
2812 
2813  for (int i = 0; i < fileLines.size(); i++) {
2814  if (elementOrder == 1) {
2815  if (fileLines[i].find("*ELEMENT, type=C3D4, ELSET=") == 0) {
2816  end = i;
2817  break;
2818  } else if (elementOrder == 2) {
2819  // Identify gmsh type for this
2820  } else {
2821  // Nothing
2822  }
2823  }
2824  }
2825 
2826  if (start == 0 || end == 0) {
2827  // No surface elements in this mesh
2828  // File will not be modified
2829  } else {
2830  // Remove part of file from vector
2831  fileLines.erase(fileLines.begin() + start, fileLines.begin() + end);
2832 
2833  // Write to a separate file for now
2834  std::ofstream outFile;
2835  outFile.open("NewModifiedMesh.inp");
2836  for (int i = 0; i < fileLines.size(); i++)
2837  outFile << fileLines[i] << std::endl;
2838  outFile.close();
2839 
2840  if (std::remove(fname.c_str()) == 0) {
2841  if (std::rename("NewModifiedMesh.inp", fname.c_str()) != 0) {
2842  std::cerr << "Could not rename file NewModifiedMesh.inp to " << fname
2843  << std::endl;
2844  throw;
2845  }
2846  } else {
2847  std::cerr << "Could not remove file " << fname << std::endl;
2848  }
2849  }
2850  } else {
2851  std::cerr << "Cannot open/find " << fname << " file!" << std::endl;
2852  throw;
2853  }
2854 }
2855 
2856 } // namespace GEO
2857 
2858 } // namespace NEM
void setSizePreservation()
Sets program for size preservation instead of volume fraction.
Definition: rocPack.C:139
int randomNodeX
For testing.
Definition: rocPack.H:536
int packGrp
Tag number.
Definition: rocPack.H:612
std::vector< std::vector< double > > rotateParams
Vector of rotate coordinates for all packs.
Definition: rocPack.H:474
void setElementOrder(const int &order)
Sets element order.
Definition: rocPack.C:141
void geomToPeriodic3D()
This method writes 3D periodic mesh into .msh and vtu format.
Definition: rocPack.C:497
void enableDefOuts()
Enables .stl, .vtu.
Definition: rocPack.C:2669
double shrinkScale
Shrink Scale.
Definition: rocPack.H:564
std::vector< int > MasterZ
Master periodic surfaces in Z direction.
Definition: rocPack.H:532
void rocPack2Surf()
rocPack2Surf method converts Rocpack output file into STL/VTK surface mesh and writes into current fo...
Definition: rocPack.C:68
double filterBelow
Lower limit for filtering.
Definition: rocPack.H:752
double Zdim
Z dimension of box geometry.
Definition: rocPack.H:445
static meshBase * exportGmshToVtk(const std::string &fname)
construct vtkMesh from gmsh msh file (called in Create methods)
Definition: meshBase.C:409
void setNodeLocations(const int &x, const int &y, const int &z)
For internal testing purpose.
Definition: rocPack.C:2264
void geomToSurf()
This method creates surface mesh for final geometry and writes into surface files (...
Definition: rocPack.C:456
bool cstmDomain
Custom Domain Boolean.
Definition: rocPack.H:636
std::vector< std::vector< std::vector< double > > > verts
Vector of crystal shape vertices.
Definition: rocPack.H:462
void writePeriodicNodes()
This method allows mapping of nodes on periodic boundaries.
Definition: rocPack.C:1935
double Xdim
X dimension of box geometry.
Definition: rocPack.H:437
std::vector< std::size_t > surrNodeTags
Stores node tags for surronding physical group.
Definition: rocPack.H:592
void removeBoundaryVolumes()
Enables an option to remove volumes intersecting boundary.
Definition: rocPack.C:104
std::string InFile
rocPack output file name
Definition: rocPack.H:416
std::vector< int > slaveInterfaceId
Storage vector for identifying which slave nodes are interface nodes.
Definition: rocPack.H:723
std::vector< int > eqRefNodes
Stores node ids n0,nx,ny,nz.
Definition: rocPack.H:709
A brief description of meshBase.
Definition: meshBase.H:64
void enablePhysicalGroupsPerShape()
Enables physical group per shape.
Definition: rocPack.C:2673
bool existsOnPeriodicBoundary(const std::vector< double > &getPt1, const std::vector< double > &getPt2, const std::vector< double > &getPt)
This method check if cohesive element face lies on any of the periodic boundaries.
Definition: rocPack.C:2761
double zUDF
Z coordinate for user-defined translate.
Definition: rocPack.H:632
A struct to respresent quaternion.
Definition: rocPack.H:45
void modifyInpMesh(const std::string &modifyFile)
Removes 2D elements from INP mesh file.
Definition: rocPack.C:2793
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
void makeEllipsoid(const int &n)
Creates Ellipsoid pack shapes.
Definition: rocPack.C:1104
int randomSurfTest
Random location for a surface.
Definition: rocPack.H:640
bool defOutputs
Output control.
Definition: rocPack.H:648
std::string OutFile
Output STL/VTK file name.
Definition: rocPack.H:420
void scaleVols(const int &vol, const int &index)
Scales all volumes by shrinking percentage.
Definition: rocPack.C:2279
std::vector< int > slaveY
Surfaces linked to master periodic surface in Y direction.
Definition: rocPack.H:516
bool removeBoundaryPacks
Boolean to opt for removing packs on boundaries.
Definition: rocPack.H:500
std::vector< std::string > Tokenize(const std::string &lineIn, const char &delim)
std::vector< int > ellipsoidPhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:676
static meshBase * Create(const std::string &fname)
Construct vtkMesh from filename.
Definition: meshBase.C:78
void setRandomSurface(const int &surf)
For internal testing purpose.
Definition: rocPack.C:2270
void setCellDataArray(const std::string &name, const std::vector< std::vector< double >> &data) override
register data to dataSet&#39;s cell data
Definition: vtkMesh.C:1007
bool enableScaling
Enables Shrinking.
Definition: rocPack.H:576
bool just2Physgrps
Enable Two Physical Groups in Final Mesh.
Definition: rocPack.H:588
double filterAbove
Upper limit for filtering.
Definition: rocPack.H:748
std::vector< int > slaveX
Surfaces linked to master periodic surface in X direction.
Definition: rocPack.H:512
std::shared_ptr< char > strToChar(const std::string &strng)
static std::shared_ptr< rocPackShape > getShape(const std::string &shapeName)
Creates shape object for requsted shape.
Definition: rocPackShape.C:38
void enableTwoPhysGrps()
Enables two physical groups in final mesh.
Definition: rocPack.C:135
int meshingAlgorithm
Meshing Algorithm.
Definition: rocPack.H:644
std::vector< double > ellipsoidRad
Vector of Ellipsoid radii.
Definition: rocPack.H:454
std::vector< std::vector< double > > translateParams
Vector of translate coordinates for all packs.
Definition: rocPack.H:470
std::vector< double > scaleOfPack
Vector of scales for all packs.
Definition: rocPack.H:478
std::vector< int > spherePhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:668
void geomToSTL(const std::string &writeFile)
This method writes periodic pack geometries into STL format.
Definition: rocPack.C:553
std::vector< std::vector< std::vector< int > > > faces
Vector of crystal shape faces.
Definition: rocPack.H:466
bool enableSizePreserve
Boolean for size preservation.
Definition: rocPack.H:764
std::vector< std::size_t > geomsNodeTags
Stores node tags for geometries physical group.
Definition: rocPack.H:600
std::vector< std::pair< int, int > > getPeriodicSurfs(const std::vector< std::vector< std::pair< int, int >>> &vertsOneSide, const std::vector< std::vector< std::pair< int, int >>> &vertsOtherSide, const int &indexTranslate, const double &amountTranslate)
This method find which surfaces are periodic on opposite sides.
Definition: rocPack.C:1887
std::vector< double > cylParams
Vector of cylinder parameters.
Definition: rocPack.H:458
int nptsMsh
Total numer of points in mesh.
Definition: rocPack.H:736
std::vector< int > icosidodecahedronPhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:688
std::vector< int > petnPhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:684
vtkSmartPointer< vtkDataSet > getDataSet() const
get this meshes&#39; dataSet
Definition: meshBase.H:308
std::vector< std::string > crystalNames
Vector for storing crystal names.
Definition: rocPack.H:432
void rocParser()
This method parses Rocpack output file and collects data for creation of pack geometries.
Definition: rocPack.C:152
std::vector< double > boxPt
Vector of box starting coordinates.
Definition: rocPack.H:449
int smoothingIter
some smoothing parameter
Definition: rocPack.H:568
bool internalCohesiveBool
Boolean to enable cohesive elements.
Definition: rocPack.H:713
void setPeriodicGeometry()
Enables an option to enforce periodicity on generated geometry.
Definition: rocPack.C:108
std::vector< int > MasterY
Master periodic surfaces in Y direction.
Definition: rocPack.H:528
void setMeshingAlgorithm(const int &mshAlg)
Sets meshing algorithm of user&#39;s choice.
Definition: rocPack.C:2665
void performSmoothing()
Performs laplacian smoothing on all packs if requested.
Definition: rocPack.C:2287
bool enableSmoothing
Enables smoothing.
Definition: rocPack.H:572
nemId_t getNumberOfPoints() const
return the number of points
Definition: meshBase.H:545
void toLower(std::string &str)
void makeSphere(const int &n)
Creates sphere pack shapes.
Definition: rocPack.C:1094
void initialize()
Initializes GMSH for workflow.
Definition: rocPack.C:143
void createVtkCell(vtkSmartPointer< vtkUnstructuredGrid > dataSet, const int cellType, std::vector< int > &vrtIds)
creates VTK cell
Definition: rocPack.C:2635
virtual void write() const
write the mesh to file named after the private var &#39;filename&#39;.
Definition: meshBase.H:598
void assignPeriodicEqNodes()
Assigns nodes n0, nx, ny, nz for periodic equation file.
Definition: rocPack.C:2675
void rocPack2Periodic3D()
rocPack2Periodic3D method converts Rocpack output file into 3D periodic mesh.
Definition: rocPack.C:82
VTKCellType cellType
Definition: inpGeoMesh.C:129
void setPeriodicMesh()
Enables an option to enforce periodicity on generated mesh.
Definition: rocPack.C:110
int randomNodeY
For testing.
Definition: rocPack.H:540
std::vector< std::size_t > interfaceNodes
Vector for stroing nodes at conformal interface.
Definition: rocPack.H:616
void geomToVTK(const std::string &writeFile)
This method writes periodic pack geometries into VTK format.
Definition: rocPack.C:558
int randomNodeZ
For testing.
Definition: rocPack.H:544
std::vector< int > slaveZ
Surfaces linked to master periodic surface in Z direction.
Definition: rocPack.H:520
void makeCylinder(const int &n)
Creates cylinder pack shapes.
Definition: rocPack.C:1266
bool enablePhysGrp
Enable Physical Grouping in Final Mesh.
Definition: rocPack.H:584
std::vector< double > surrCoords
Stores node coordinates for surronding physical group.
Definition: rocPack.H:596
bool getTestResult()
This method is for internal testing purpose only.
Definition: rocPack.C:2272
bool matchingCoordsY
Y Nodes for testing.
Definition: rocPack.H:556
std::vector< std::string > getShapeData(const int &iter, const std::string &a, const std::vector< std::string > &L)
Reads the current line and returns the translate, rotate, and scale data for the pack shape...
Definition: rocPack.C:1088
double meshSz
Mesh Size.
Definition: rocPack.H:580
void geomToMsh(const std::string &writeFile)
This method writes periodic pack geometries into .MSH format.
Definition: rocPack.C:571
void sanityCheckOn()
Sanity check for cohesive element method when there are no volumes in domain.
Definition: rocPack.C:2671
std::vector< int > geomElementIds
Store cells in surrounding for cohesive elements without physical groups.
Definition: rocPack.H:705
void enablePhysicalGrps()
Enables physical grouping in final mesh.
Definition: rocPack.C:133
void enableSurfacePatches()
Enables 6 surface patches for all sides of box.
Definition: rocPack.C:137
void assignRefinement(const int &refineLvl)
Assigns refinement levels to mesh.
Definition: rocPack.C:124
void createCohesiveElements(const std::string &filename, const std::string &outname)
This method creates cohesive elements using existing vtu file.
Definition: rocPack.C:2298
std::string findWord(const std::string &word)
Finds particular word in file stream.
Definition: rocPack.C:1080
rocQuaternion toQuaternion(const std::vector< double > &r)
Generates a Quaternion using Euler 3D rotation parameters.
Definition: rocPack.C:1544
void smoothSurfaces(const int smoothingParam)
Performs surface smoothing over every volume in pack geometry.
Definition: rocPack.C:117
std::map< std::string, std::vector< std::pair< vtkIdType, int > > > surfaces
Map from SURFACE name to (element id, side) (id and side both use .inp IDs)
Definition: inpGeoMesh.C:157
std::map< int, int > storeShapeNames
Map for storing shape names against volume Sphere = 0 Ellipsoid = 1 Cylinder = 2 HMX = 3 PETN = 4 Ico...
Definition: rocPack.H:664
std::vector< std::vector< std::pair< int, int > > > getAllPoints(std::vector< std::pair< int, int >> surfaces)
This method gets points that belongs to surfaces.
Definition: rocPack.C:1869
bool assignSidePatches
A boolean for user to enable assignement of surface patches.
Definition: rocPack.H:620
std::vector< int > multiGrpIndices
Group indices for multi groups (useful in cohesive elements)
Definition: rocPack.H:700
std::vector< int > hmxPhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:680
bool ellipsoidPresent
Ellipsoid packs cannot be made periodic as of now.
Definition: rocPack.H:491
void setMeshSize(const double size)
Set mesh size for periodic mesh.
Definition: rocPack.C:122
void makePeriodic(const bool rmbPacks)
Enforced periodicity on geometry.
Definition: rocPack.C:576
std::vector< int > ptsReplacer
Storage vector for linking interface and duplicate nodes Replaces new duplicated nodes at place of ol...
Definition: rocPack.H:718
std::vector< std::string > uniqueNames
Vector for storing shapes.
Definition: rocPack.H:428
void rocToGeom()
This method obtains parsed data from Rocpack output and creates periodic pack geometries.
Definition: rocPack.C:385
double yUDF
Y coordinate for user-defined translate.
Definition: rocPack.H:628
void tagBoundaryPacks()
This method removes the pack shapes intersecting boundary.
Definition: rocPack.C:1478
void translateAll(const double &X, const double &Y, const double &Z)
Translates the whole geometry along user-defined parameters.
Definition: rocPack.C:2644
int surroundingGrp
Tag number.
Definition: rocPack.H:608
double Ydim
Y dimension of box geometry.
Definition: rocPack.H:441
bool physGrpPerShape
Boolean for physical group per shape.
Definition: rocPack.H:652
void enableCohesiveElements()
Enables cohesive elements.
Definition: rocPack.C:106
virtual void getCellDataArray(const std::string &name, std::vector< double > &data)
<>
Definition: meshBase.H:369
void setCustomDomain(const std::vector< double > &domainBounds)
Sets custom domain size defined by users.
Definition: rocPack.C:2650
bool matchingCoordsZ
Z Nodes for testing.
Definition: rocPack.H:560
std::vector< std::string > nameOfPcks
Vector of pack shape names.
Definition: rocPack.H:482
double xUDF
X coordinate for user-defined translate.
Definition: rocPack.H:624
bool matchingCoordsX
X Nodes for testing.
Definition: rocPack.H:552
void applyFilter(const double &upperThreshold, const double &lowerThreshold)
Assigns limiting filters for geometry sizes.
Definition: rocPack.C:126
std::vector< std::vector< int > > storeMultiPhysGrps
Stores all physical groups in index sized by total volumes.
Definition: rocPack.H:696
int refineIter
mesh refinement iterations
Definition: rocPack.H:744
bool filterOn
Boolean for filter.
Definition: rocPack.H:756
std::vector< double > rotateByQuaternion(const rocQuaternion &q, const std::vector< double > &v)
Rotates a 3D Vector by unit Quaternion.
Definition: rocPack.C:1523
std::vector< std::pair< int, int > > bndryPackTags
Stores volume index of packs interseting boundary.
Definition: rocPack.H:504
void shrinkVolumes(const double percntg)
Shrinks the volumes by defined percentage.
Definition: rocPack.C:112
std::vector< int > filteredGeoms
Vector for identification of removed geometries.
Definition: rocPack.H:760
std::vector< std::string > shapeNames
Vector for storing base shape names.
Definition: rocPack.H:424
std::vector< int > MasterX
Master periodic surfaces in X direction.
Definition: rocPack.H:524
nemId_t getNumberOfCells() const
return the number of cells
Definition: meshBase.H:550
std::vector< int > cylindersPhysicalGroup
Arrays for group per shape.
Definition: rocPack.H:672
void normalizeVerts()
Normalizes shape vertices.
Definition: rocPack.C:1460
std::vector< int > linkMultiPhysGrps
Vector of all volumes for multi-physical groups.
Definition: rocPack.H:692
std::vector< int > ptsCohesiveGrp
psudo-physical group vector for cohesive elements material assignment
Definition: rocPack.H:728
bool enablePeriodicity
Boolean to opt for non-periodic geometry (as generated by rocPack)
Definition: rocPack.H:495
bool sntChk
Sanity Check.
Definition: rocPack.H:732
double globalScaling
Global scale for all pack geometries.
Definition: rocPack.H:740
void report() const override
generate a report of the mesh
Definition: vtkMesh.C:780
void write() const override
write the mesh to file named after the private var &#39;filename&#39;.
Definition: vtkMesh.H:152
rocPack(const std::string &fname, const std::string &outName)
rocPack default constructor.
Definition: rocPack.C:62
std::vector< double > geomsCoords
Stores node coordinates for geometries physical group.
Definition: rocPack.H:604
void mapPeriodicSurfaces(const std::vector< std::pair< int, int >> &prevTags)
This method maps surfaces in X,Y, and Z direction which are periodic and then enforces that into gmsh...
Definition: rocPack.C:1556
void makeCrystalShape(const int &n, const int &index)
Creates a crystal shape based on Rocpack output file.
Definition: rocPack.C:1370
int elementOrder
Sets mesh element order.
Definition: rocPack.H:768
bool periodic3D
Boolean for 3D periodic mesh generation.
Definition: rocPack.H:508