Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Member Functions | Private Attributes | List of all members
Nektar::NekMeshUtils::Generator2D Class Reference

class containing all surface meshing routines methods and classes More...

#include <2DGenerator.h>

Inheritance diagram for Nektar::NekMeshUtils::Generator2D:
[legend]

Public Member Functions

 Generator2D (MeshSharedPtr m)
 
virtual ~Generator2D ()
 
virtual void Process ()
 
- Public Member Functions inherited from Nektar::NekMeshUtils::ProcessModule
NEKMESHUTILS_EXPORT ProcessModule (MeshSharedPtr p_m)
 
- Public Member Functions inherited from Nektar::NekMeshUtils::Module
NEKMESHUTILS_EXPORT Module (MeshSharedPtr p_m)
 
NEKMESHUTILS_EXPORT void RegisterConfig (std::string key, std::string value=std::string())
 Register a configuration option with a module. More...
 
NEKMESHUTILS_EXPORT void PrintConfig ()
 Print out all configuration options for a module. More...
 
NEKMESHUTILS_EXPORT void SetDefaults ()
 Sets default configuration options for those which have not been set. More...
 
NEKMESHUTILS_EXPORT MeshSharedPtr GetMesh ()
 
virtual NEKMESHUTILS_EXPORT void ProcessVertices ()
 Extract element vertices. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessEdges (bool ReprocessEdges=true)
 Extract element edges. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessFaces (bool ReprocessFaces=true)
 Extract element faces. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessElements ()
 Generate element IDs. More...
 
virtual NEKMESHUTILS_EXPORT void ProcessComposites ()
 Generate composites. More...
 
virtual NEKMESHUTILS_EXPORT void ClearElementLinks ()
 

Static Public Member Functions

static std::shared_ptr< Modulecreate (MeshSharedPtr m)
 Creates an instance of this class. More...
 

Static Public Attributes

static ModuleKey className
 

Private Member Functions

void FindBLEnds ()
 
void MakeBLPrep ()
 
void PeriodicPrep ()
 
void MakePeriodic ()
 
void MakeBL (int faceid)
 
void Report ()
 

Private Attributes

std::map< int, FaceMeshSharedPtrm_facemeshes
 map of individual surface meshes from parametric surfaces More...
 
std::map< int, CurveMeshSharedPtrm_curvemeshes
 map of individual curve meshes of the curves in the domain More...
 
std::map< unsigned, unsigned > m_periodicPairs
 map of periodic curve pairs More...
 
std::vector< unsigned int > m_blCurves
 list of curves needing a BL More...
 
std::map< unsigned, unsigned > m_blends
 map of curves and Bl ends: 0, 1 or 2 (for both) More...
 
std::vector< EdgeSharedPtrm_blEdges
 list of BL edges More...
 
LibUtilities::Interpreter m_thickness
 BL thickness expression. More...
 
int m_thickness_ID
 BL thickness expression ID. More...
 
std::map< NodeSharedPtr, std::vector< EdgeSharedPtr > > m_nodesToEdge
 map of BL curve nodes to adjacent edges More...
 

Additional Inherited Members

- Protected Member Functions inherited from Nektar::NekMeshUtils::Module
NEKMESHUTILS_EXPORT void ReorderPrisms (PerMap &perFaces)
 Reorder node IDs so that prisms and tetrahedra are aligned correctly. More...
 
NEKMESHUTILS_EXPORT void PrismLines (int prism, PerMap &perFaces, std::set< int > &prismsDone, std::vector< ElementSharedPtr > &line)
 
- Protected Attributes inherited from Nektar::NekMeshUtils::Module
MeshSharedPtr m_mesh
 Mesh object. More...
 
std::map< std::string, ConfigOptionm_config
 List of configuration values. More...
 

Detailed Description

class containing all surface meshing routines methods and classes

Definition at line 52 of file 2DGenerator.h.

Constructor & Destructor Documentation

◆ Generator2D()

Nektar::NekMeshUtils::Generator2D::Generator2D ( MeshSharedPtr  m)

Definition at line 56 of file 2DGenerator.cpp.

References Nektar::NekMeshUtils::Module::m_config.

56  : ProcessModule(m)
57 {
58  m_config["blcurves"] =
59  ConfigOption(false, "", "Generate parallelograms on these curves");
60  m_config["blthick"] =
61  ConfigOption(false, "0.0", "Parallelogram layer thickness");
62  m_config["periodic"] =
63  ConfigOption(false, "", "Set of pairs of periodic curves");
64  m_config["bltadjust"] =
65  ConfigOption(false, "2.0", "Boundary layer thickness adjustment");
66  m_config["adjustblteverywhere"] =
67  ConfigOption(true, "0", "Adjust thickness everywhere");
68  m_config["smoothbl"] =
69  ConfigOption(true, "0", "Smooth the BL normal directions to avoid "
70  "(nearly) intersecting normals");
71  m_config["spaceoutbl"] = ConfigOption(
72  false, "0.5", "Threshold to space out BL according to Delta");
73  m_config["nospaceoutsurf"] =
74  ConfigOption(false, "", "Surfaces where spacing out shouldn't be used");
75 }
NEKMESHUTILS_EXPORT ProcessModule(MeshSharedPtr p_m)
std::map< std::string, ConfigOption > m_config
List of configuration values.

◆ ~Generator2D()

Nektar::NekMeshUtils::Generator2D::~Generator2D ( )
virtual

Definition at line 77 of file 2DGenerator.cpp.

78 {
79 }

Member Function Documentation

◆ create()

static std::shared_ptr<Module> Nektar::NekMeshUtils::Generator2D::create ( MeshSharedPtr  m)
inlinestatic

Creates an instance of this class.

Definition at line 56 of file 2DGenerator.h.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr().

57  {
59  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.

◆ FindBLEnds()

void Nektar::NekMeshUtils::Generator2D::FindBLEnds ( )
private

Definition at line 244 of file 2DGenerator.cpp.

References Nektar::StdRegions::find(), m_blCurves, m_blends, and Nektar::NekMeshUtils::Module::m_mesh.

Referenced by Process().

245 {
246  // Set of CAD vertices
247  // Vertices of each curve are added to the set if not found and removed from
248  // the set if found
249  // This leaves us with a set of vertices that are at the end of BL open
250  // loops
251  set<CADVertSharedPtr> cadverts;
252 
253  for (auto &it : m_blCurves)
254  {
255  vector<CADVertSharedPtr> vertices =
256  m_mesh->m_cad->GetCurve(it)->GetVertex();
257 
258  for (auto &iv : vertices)
259  {
260  set<CADVertSharedPtr>::iterator is = cadverts.find(iv);
261 
262  if (is != cadverts.end())
263  {
264  cadverts.erase(is);
265  }
266  else
267  {
268  cadverts.insert(iv);
269  }
270  }
271  }
272 
273  // Build m_blends based on the previously constructed set of vertices
274  // m_blends is a map of curve number (the curves right outside the BL open
275  // loops) to the offset node number: 0, 1 or 2 (for both)
276  for (int i = 1; i <= m_mesh->m_cad->GetNumCurve(); ++i)
277  {
278  if (find(m_blCurves.begin(), m_blCurves.end(), i) != m_blCurves.end())
279  {
280  continue;
281  }
282 
283  vector<CADVertSharedPtr> vertices =
284  m_mesh->m_cad->GetCurve(i)->GetVertex();
285 
286  for (int j = 0; j < 2; ++j)
287  {
288  if (!cadverts.count(vertices[j]))
289  {
290  continue;
291  }
292 
293  if (m_blends.count(i))
294  {
295  m_blends[i] = 2;
296  }
297  else
298  {
299  m_blends[i] = j;
300  }
301  }
302  }
303 }
std::vector< unsigned int > m_blCurves
list of curves needing a BL
Definition: 2DGenerator.h:87
std::map< unsigned, unsigned > m_blends
map of curves and Bl ends: 0, 1 or 2 (for both)
Definition: 2DGenerator.h:89
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:358

◆ MakeBL()

void Nektar::NekMeshUtils::Generator2D::MakeBL ( int  faceid)
private

Definition at line 326 of file 2DGenerator.cpp.

References Nektar::NekMeshUtils::Node::abs2(), Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::NekMeshUtils::Node::curl(), Nektar::NekMeshUtils::CADOrientation::eBackwards, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::Interpreter::Evaluate(), Nektar::StdRegions::find(), Nektar::ParseUtils::GenerateSeqVector(), Nektar::NekMeshUtils::GetElementFactory(), CG_Iterations::loc, m_blCurves, m_blEdges, Nektar::NekMeshUtils::Module::m_config, m_curvemeshes, Nektar::NekMeshUtils::Module::m_mesh, m_nodesToEdge, m_thickness, m_thickness_ID, Nektar::NekMeshUtils::Node::m_x, Nektar::NekMeshUtils::Node::m_y, Nektar::NekMeshUtils::Node::m_z, class_topology::Node, CellMLToNektar.cellml_metadata::p, and WARNINGL0.

Referenced by Process().

327 {
328  map<int, Array<OneD, NekDouble>> edgeNormals;
329  int eid = 0;
330  for (auto &it : m_blCurves)
331  {
333  m_mesh->m_cad->GetCurve(it)->GetOrienationWRT(faceid);
334  vector<EdgeSharedPtr> es = m_curvemeshes[it]->GetMeshEdges();
335  // on each !!!EDGE!!! calculate a normal
336  // always to the left unless edgeo is 1
337  // normal must be done in the parametric space (and then projected back)
338  // because of face orientation
339  for (auto &ie : es)
340  {
341  ie->m_id = eid++;
342  Array<OneD, NekDouble> p1, p2;
343  p1 = ie->m_n1->GetCADSurfInfo(faceid);
344  p2 = ie->m_n2->GetCADSurfInfo(faceid);
345  Array<OneD, NekDouble> n(2);
346  n[0] = p1[1] - p2[1];
347  n[1] = p2[0] - p1[0];
348  if (edgeo == CADOrientation::eBackwards)
349  {
350  n[0] *= -1.0;
351  n[1] *= -1.0;
352  }
353  NekDouble mag = sqrt(n[0] * n[0] + n[1] * n[1]);
354  n[0] /= mag;
355  n[1] /= mag;
356  Array<OneD, NekDouble> np(2);
357  np[0] = p1[0] + n[0];
358  np[1] = p1[1] + n[1];
359  Array<OneD, NekDouble> loc = ie->m_n1->GetLoc();
360  Array<OneD, NekDouble> locp = m_mesh->m_cad->GetSurf(faceid)->P(np);
361  n[0] = locp[0] - loc[0];
362  n[1] = locp[1] - loc[1];
363  mag = sqrt(n[0] * n[0] + n[1] * n[1]);
364  n[0] /= mag;
365  n[1] /= mag;
366  edgeNormals[ie->m_id] = n;
367  }
368  }
369 
370  bool adjust = m_config["bltadjust"].beenSet;
371  NekDouble divider = m_config["bltadjust"].as<NekDouble>();
372  bool adjustEverywhere = m_config["adjustblteverywhere"].beenSet;
373  bool smoothbl = m_config["smoothbl"].beenSet;
374  bool spaceoutbl = m_config["spaceoutbl"].beenSet;
375  NekDouble spaceoutthr = m_config["spaceoutbl"].as<NekDouble>();
376 
377  if (divider < 2.0)
378  {
379  WARNINGL0(false, "BndLayerAdjustment too low, corrected to 2.0");
380  divider = 2.0;
381  }
382 
383  map<NodeSharedPtr, NodeSharedPtr> nodeNormals;
384  for (auto &it : m_nodesToEdge)
385  {
386  ASSERTL0(it.second.size() == 1 || it.second.size() == 2,
387  "weirdness, most likely bl_surfs are incorrect");
388 
389  // If node at the end of the BL open loop, the "normal node" isn't
390  // constructed by computing a normal but found on the adjacent curve
391  if (it.second.size() == 1)
392  {
393  vector<CADCurveSharedPtr> curves = it.first->GetCADCurves();
394 
395  vector<EdgeSharedPtr> edges =
396  m_curvemeshes[curves[0]->GetId()]->GetMeshEdges();
397  vector<EdgeSharedPtr>::iterator ie =
398  find(edges.begin(), edges.end(), it.second[0]);
399  int rightCurve =
400  (ie == edges.end()) ? curves[0]->GetId() : curves[1]->GetId();
401 
402  vector<NodeSharedPtr> nodes =
403  m_curvemeshes[rightCurve]->GetMeshPoints();
404  nodeNormals[it.first] =
405  (nodes[0] == it.first) ? nodes[1] : nodes[nodes.size() - 2];
406 
407  continue;
408  }
409 
410  Array<OneD, NekDouble> n(3, 0.0);
411  Array<OneD, NekDouble> n1 = edgeNormals[it.second[0]->m_id];
412  Array<OneD, NekDouble> n2 = edgeNormals[it.second[1]->m_id];
413  n[0] = (n1[0] + n2[0]) / 2.0;
414  n[1] = (n1[1] + n2[1]) / 2.0;
415  NekDouble mag = sqrt(n[0] * n[0] + n[1] * n[1]);
416  n[0] /= mag;
417  n[1] /= mag;
418  NekDouble t = m_thickness.Evaluate(m_thickness_ID, it.first->m_x,
419  it.first->m_y, 0.0, 0.0);
420  // Adjust thickness according to angle between normals
421  if (adjust)
422  {
423  if (adjustEverywhere || it.first->GetNumCadCurve() > 1)
424  {
425  NekDouble angle = acos(n1[0] * n2[0] + n1[1] * n2[1]);
426  angle = (angle > M_PI) ? 2 * M_PI - angle : angle;
427  t /= cos(angle / divider);
428  }
429  }
430 
431  n[0] = n[0] * t + it.first->m_x;
432  n[1] = n[1] * t + it.first->m_y;
433  NodeSharedPtr nn = std::shared_ptr<Node>(
434  new Node(m_mesh->m_numNodes++, n[0], n[1], 0.0));
435  CADSurfSharedPtr s = m_mesh->m_cad->GetSurf(faceid);
436  Array<OneD, NekDouble> uv = s->locuv(n);
437  nn->SetCADSurf(s, uv);
438  nodeNormals[it.first] = nn;
439  }
440 
441  // Check for any intersecting boundary layer normals and smooth them if
442  // needed
443  if (smoothbl)
444  {
445  // Nodes that need normal smoothing and their unit normal
446  map<NodeSharedPtr, vector<NodeSharedPtr>> unitNormals;
447  // Nodes that need normal smoothing and their BL thickness
448  map<NodeSharedPtr, NekDouble> dist;
449 
450  int count = 0;
451 
452  do
453  {
454  unitNormals.clear();
455  dist.clear();
456 
457  for (const auto &it : m_blEdges)
458  {
459  // Line intersection based on
460  // https://stackoverflow.com/a/565282/7241595
461  NodeSharedPtr p = it->m_n1;
462  NodeSharedPtr q = it->m_n2;
463 
464  Node r = *nodeNormals[p] - *p;
465  Node s = *nodeNormals[q] - *q;
466 
467  NekDouble d = r.curl(s).m_z;
468 
469  // Should probably use tolerance to check parallelism
470  if (d == 0)
471  {
472  continue;
473  }
474 
475  NekDouble t = (*q - *p).curl(s).m_z / d;
476  NekDouble u = (*q - *p).curl(r).m_z / d;
477 
478  // Check for intersection of the infinite continuation of one
479  // normal with the other. A tolerance of 0.5 times the length of
480  // thenormalis used. Could maybe be decreased to a less
481  // aggressive value.
482  if ((-0.5 < t && t <= 1.5) || (-0.5 < u && u <= 1.5))
483  {
484  dist[p] = sqrt(r.abs2());
485  dist[q] = sqrt(s.abs2());
486 
487  NodeSharedPtr sum =
488  make_shared<Node>(r / dist[p] + s / dist[q]);
489 
490  unitNormals[p].push_back(sum);
491  unitNormals[q].push_back(sum);
492  }
493  }
494 
495  // Smooth each normal one by one
496  for (const auto &it : unitNormals)
497  {
498  Node avg(0, 0.0, 0.0, 0.0);
499 
500  for (const auto &i : it.second)
501  {
502  avg += *i;
503  }
504 
505  avg /= sqrt(avg.abs2());
506 
507  // Create new BL node with smoothed normal
508  NodeSharedPtr nn = std::shared_ptr<Node>(
509  new Node(nodeNormals[it.first]->GetID(),
510  it.first->m_x + avg.m_x * dist[it.first],
511  it.first->m_y + avg.m_y * dist[it.first], 0.0));
512  CADSurfSharedPtr s =
513  *nodeNormals[it.first]->GetCADSurfs().begin();
514  Array<OneD, NekDouble> uv = s->locuv(nn->GetLoc());
515  nn->SetCADSurf(s, uv);
516 
517  nodeNormals[it.first] = nn;
518  }
519  } while (unitNormals.size() && count++ < 50);
520 
521  if (m_mesh->m_verbose)
522  {
523  if (count < 50)
524  {
525  cout << "\t\tNormals smoothed in " << count << " iterations."
526  << endl;
527  }
528  else
529  {
530  cout << "\t\tNormals smoothed. Algorithm didn't converge after "
531  << count << " iterations." << endl;
532  }
533  }
534  }
535 
536  // Space out the outter BL nodes to better fit the local required Delta
537  if (spaceoutbl)
538  {
539  if (spaceoutthr < 0.0 || spaceoutthr > 1.0)
540  {
541  WARNINGL0(false, "The boundary layer space out threshold should be "
542  "between 0 and 1. It will now be adjusted to "
543  "0.5.");
544  spaceoutthr = 0.5;
545  }
546 
547  vector<unsigned int> nospaceoutsurf;
548  ParseUtils::GenerateSeqVector(m_config["nospaceoutsurf"].as<string>(),
549  nospaceoutsurf);
550 
551  // List of connected nodes at need spacing out
552  vector<deque<NodeSharedPtr>> nodesToMove;
553 
554  int count = 0;
555 
556  // This will supposedly spread the number of nodes to be moved until
557  // sufficient space is found
558  do
559  {
560  nodesToMove.clear();
561 
562  // Find which nodes need to be spaced out
563  for (const auto &ie : m_blEdges)
564  {
565  auto it = find(nospaceoutsurf.begin(), nospaceoutsurf.end(),
566  ie->m_parentCAD->GetId());
567  if (it != nospaceoutsurf.end())
568  {
569  continue;
570  }
571 
572  NodeSharedPtr n1 = nodeNormals[ie->m_n1];
573  NodeSharedPtr n2 = nodeNormals[ie->m_n2];
574 
575  NekDouble targetD =
576  m_mesh->m_octree->Query(((*n1 + *n2) / 2.0).GetLoc());
577  NekDouble realD = sqrt((*n1 - *n2).abs2());
578 
579  // Add nodes if condition fulfilled
580  if (realD < spaceoutthr * targetD)
581  {
582  bool connected = false;
583 
584  for (auto &il : nodesToMove)
585  {
586  if (il.front() == n1)
587  {
588  il.push_front(n2);
589  connected = true;
590  break;
591  }
592  if (il.front() == n2)
593  {
594  il.push_front(n1);
595  connected = true;
596  break;
597  }
598  if (il.back() == n1)
599  {
600  il.push_back(n2);
601  connected = true;
602  break;
603  }
604  if (il.back() == n2)
605  {
606  il.push_back(n1);
607  connected = true;
608  break;
609  }
610  }
611 
612  // Create new set of connected nodes if necessary
613  if (!connected)
614  {
615  deque<NodeSharedPtr> newList;
616  newList.push_back(n1);
617  newList.push_back(n2);
618 
619  nodesToMove.push_back(newList);
620  }
621  }
622  }
623 
624  for (int i = 0;; ++i)
625  {
626  // Reconnect sets of connected nodes together if need be. Done
627  // once before ad once after expanding the set by one node to
628  // find extra space.
629  for (int i1 = 0; i1 < nodesToMove.size(); ++i1)
630  {
631  NodeSharedPtr n11 = nodesToMove[i1].front();
632  NodeSharedPtr n12 = nodesToMove[i1].back();
633 
634  for (int i2 = i1 + 1; i2 < nodesToMove.size(); ++i2)
635  {
636  NodeSharedPtr n21 = nodesToMove[i2].front();
637  NodeSharedPtr n22 = nodesToMove[i2].back();
638 
639  if (n11 == n21 || n11 == n22 || n12 == n21 ||
640  n12 == n22)
641  {
642  if (n11 == n21 || n12 == n22)
643  {
644  reverse(nodesToMove[i2].begin(),
645  nodesToMove[i2].end());
646  n21 = nodesToMove[i2].front();
647  n22 = nodesToMove[i2].back();
648  }
649 
650  if (n11 == n22)
651  {
652  nodesToMove[i1].insert(nodesToMove[i1].begin(),
653  nodesToMove[i2].begin(),
654  nodesToMove[i2].end() -
655  1);
656  }
657  else
658  {
659  nodesToMove[i1].insert(nodesToMove[i1].end(),
660  nodesToMove[i2].begin() +
661  1,
662  nodesToMove[i2].end());
663  }
664 
665  nodesToMove.erase(nodesToMove.begin() + i2);
666  continue;
667  }
668  }
669  }
670 
671  if (i >= 1)
672  {
673  break;
674  }
675 
676  set<EdgeSharedPtr> addedEdges;
677 
678  // Expand each set of connected nodes by one node to allow for
679  // extra space
680  for (auto &il : nodesToMove)
681  {
682  NodeSharedPtr n11 = *(il.begin() + 0);
683  NodeSharedPtr n12 = *(il.begin() + 1);
684 
685  NodeSharedPtr n13 = *(il.rbegin() + 1);
686  NodeSharedPtr n14 = *(il.rbegin() + 0);
687 
688  for (const auto &ie : m_blEdges)
689  {
690  auto it =
691  find(nospaceoutsurf.begin(), nospaceoutsurf.end(),
692  ie->m_parentCAD->GetId());
693  if (addedEdges.count(ie) || it != nospaceoutsurf.end())
694  {
695  continue;
696  }
697 
698  NodeSharedPtr n21 = nodeNormals[ie->m_n1];
699  NodeSharedPtr n22 = nodeNormals[ie->m_n2];
700 
701  NodeSharedPtr frontPush, backPush;
702 
703  if (n11)
704  {
705  if (n11 == n21 && n12 != n22)
706  {
707  frontPush = n22;
708  }
709  else if (n11 == n22 && n12 != n21)
710  {
711  frontPush = n21;
712  }
713 
714  if (frontPush)
715  {
716  il.push_front(frontPush);
717  n11.reset();
718  addedEdges.insert(ie);
719  }
720  }
721  if (n14 && !frontPush)
722  {
723  if (n14 == n21 && n13 != n22)
724  {
725  backPush = n22;
726  }
727  if (n14 == n22 && n13 != n21)
728  {
729  backPush = n21;
730  }
731 
732  if (backPush)
733  {
734  il.push_back(backPush);
735  n14.reset();
736  addedEdges.insert(ie);
737  }
738  }
739 
740  if (!n11 && !n14)
741  {
742  break;
743  }
744  }
745  }
746  }
747 
748  // Actual spacing out of the nodes. Done by simple linear
749  // interpolation between the 2 end nodes. Weights come from the
750  // required Delta or each edge.
751  for (const auto &il : nodesToMove)
752  {
753  NodeSharedPtr ni = il.front();
754  NodeSharedPtr nf = il.back();
755 
756  vector<NekDouble> deltas;
757  NekDouble total = 0.0;
758 
759  for (int i = 0; i < il.size() - 1; ++i)
760  {
761  NodeSharedPtr n1 = il[i];
762  NodeSharedPtr n2 = il[i + 1];
763 
764  deltas.push_back(
765  m_mesh->m_octree->Query(((*n1 + *n2) / 2.0).GetLoc()));
766  total += deltas.back();
767  }
768 
769  for (auto &id : deltas)
770  {
771  id /= total;
772  }
773 
774  NekDouble runningTotal = 0.0;
775 
776  for (int i = 1; i < il.size() - 1; ++i)
777  {
778  runningTotal += deltas[i - 1];
779  Array<OneD, NekDouble> loc =
780  (*ni * (1.0 - runningTotal) + *nf * runningTotal)
781  .GetLoc();
782 
783  Array<OneD, NekDouble> uv =
784  m_mesh->m_cad->GetSurf(faceid)->locuv(loc);
785 
786  il[i]->Move(loc, faceid, uv);
787  }
788  }
789  } while (nodesToMove.size() && count++ < 50);
790 
791  if (m_mesh->m_verbose)
792  {
793  if (count < 50)
794  {
795  cout << "\t\tBL spaced out in " << count << " iterations."
796  << endl;
797  }
798  else
799  {
800  cout << "\t\tBL spaced out. Algorithm didn't converge after "
801  << count << " iterations." << endl;
802  }
803  }
804  }
805 
806  for (auto &it : m_blCurves)
807  {
809  m_mesh->m_cad->GetCurve(it)->GetOrienationWRT(faceid);
810  vector<NodeSharedPtr> ns = m_curvemeshes[it]->GetMeshPoints();
811  vector<NodeSharedPtr> newNs;
812  for (auto &in : ns)
813  {
814  newNs.push_back(nodeNormals[in]);
815  }
816  m_curvemeshes[it] =
818  if (edgeo == CADOrientation::eBackwards)
819  {
820  reverse(ns.begin(), ns.end());
821  }
822  for (int i = 0; i < ns.size() - 1; ++i)
823  {
824  vector<NodeSharedPtr> qns;
825  qns.push_back(ns[i]);
826  qns.push_back(ns[i + 1]);
827  qns.push_back(nodeNormals[ns[i + 1]]);
828  qns.push_back(nodeNormals[ns[i]]);
829  ElmtConfig conf(LibUtilities::eQuadrilateral, 1, false, false);
830  vector<int> tags;
831  tags.push_back(101);
833  LibUtilities::eQuadrilateral, conf, qns, tags);
834  E->m_parentCAD = m_mesh->m_cad->GetSurf(faceid);
835  for (int j = 0; j < E->GetEdgeCount(); ++j)
836  {
837  pair<EdgeSet::iterator, bool> testIns;
838  EdgeSharedPtr ed = E->GetEdge(j);
839  // look for edge in m_mesh edgeset from curves
840  EdgeSet::iterator s = m_mesh->m_edgeSet.find(ed);
841  if (!(s == m_mesh->m_edgeSet.end()))
842  {
843  ed = *s;
844  E->SetEdge(j, *s);
845  }
846  }
847  m_mesh->m_element[2].push_back(E);
848  }
849  }
850 }
std::shared_ptr< CADSurf > CADSurfSharedPtr
Definition: CADCurve.h:51
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::vector< unsigned int > m_blCurves
list of curves needing a BL
Definition: 2DGenerator.h:87
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
std::shared_ptr< Node > NodeSharedPtr
Definition: CADVert.h:49
int m_thickness_ID
BL thickness expression ID.
Definition: 2DGenerator.h:95
LibUtilities::Interpreter m_thickness
BL thickness expression.
Definition: 2DGenerator.h:93
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
#define WARNINGL0(condition, msg)
Definition: ErrorUtil.hpp:223
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::vector< EdgeSharedPtr > m_blEdges
list of BL edges
Definition: 2DGenerator.h:91
double NekDouble
std::map< std::string, ConfigOption > m_config
List of configuration values.
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:358
std::map< NodeSharedPtr, std::vector< EdgeSharedPtr > > m_nodesToEdge
map of BL curve nodes to adjacent edges
Definition: 2DGenerator.h:97
std::map< int, CurveMeshSharedPtr > m_curvemeshes
map of individual curve meshes of the curves in the domain
Definition: 2DGenerator.h:83
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector. ...
Definition: ParseUtils.cpp:108

◆ MakeBLPrep()

void Nektar::NekMeshUtils::Generator2D::MakeBLPrep ( )
private

Definition at line 305 of file 2DGenerator.cpp.

References m_blCurves, m_blEdges, m_curvemeshes, Nektar::NekMeshUtils::Module::m_mesh, and m_nodesToEdge.

Referenced by Process().

306 {
307  if (m_mesh->m_verbose)
308  {
309  cout << endl << "\tBoundary layer meshing:" << endl << endl;
310  }
311 
312  // identify the nodes and edges which will become the boundary layer.
313 
314  for (auto &it : m_blCurves)
315  {
316  vector<EdgeSharedPtr> localedges = m_curvemeshes[it]->GetMeshEdges();
317  for (auto &ie : localedges)
318  {
319  m_blEdges.push_back(ie);
320  m_nodesToEdge[ie->m_n1].push_back(ie);
321  m_nodesToEdge[ie->m_n2].push_back(ie);
322  }
323  }
324 }
std::vector< unsigned int > m_blCurves
list of curves needing a BL
Definition: 2DGenerator.h:87
std::vector< EdgeSharedPtr > m_blEdges
list of BL edges
Definition: 2DGenerator.h:91
std::map< NodeSharedPtr, std::vector< EdgeSharedPtr > > m_nodesToEdge
map of BL curve nodes to adjacent edges
Definition: 2DGenerator.h:97
std::map< int, CurveMeshSharedPtr > m_curvemeshes
map of individual curve meshes of the curves in the domain
Definition: 2DGenerator.h:83

◆ MakePeriodic()

void Nektar::NekMeshUtils::Generator2D::MakePeriodic ( )
private

Definition at line 883 of file 2DGenerator.cpp.

References m_curvemeshes, Nektar::NekMeshUtils::Module::m_mesh, and m_periodicPairs.

Referenced by Process().

884 {
885  // Override slave curves
886 
887  for (auto &ip : m_periodicPairs)
888  {
889  m_curvemeshes[ip.second]->PeriodicOverwrite(m_curvemeshes[ip.first]);
890  }
891 
892  if (m_mesh->m_verbose)
893  {
894  cout << "\t\tPeriodic boundary conditions" << endl;
895  for (auto &it : m_periodicPairs)
896  {
897  cout << "\t\t\tCurves " << it.first << " => " << it.second << endl;
898  }
899  cout << endl;
900  }
901 }
std::map< unsigned, unsigned > m_periodicPairs
map of periodic curve pairs
Definition: 2DGenerator.h:85
std::map< int, CurveMeshSharedPtr > m_curvemeshes
map of individual curve meshes of the curves in the domain
Definition: 2DGenerator.h:83

◆ PeriodicPrep()

void Nektar::NekMeshUtils::Generator2D::PeriodicPrep ( )
private

Definition at line 852 of file 2DGenerator.cpp.

References ASSERTL0, Nektar::NekMeshUtils::Module::m_config, and m_periodicPairs.

Referenced by Process().

853 {
854  m_periodicPairs.clear();
855  set<unsigned> periodic;
856 
857  // Build periodic curve pairs
858  string s = m_config["periodic"].as<string>();
859  vector<string> lines;
860 
861  boost::split(lines, s, boost::is_any_of(":"));
862 
863  for (auto &il : lines)
864  {
865  vector<string> tmp;
866  boost::split(tmp, il, boost::is_any_of(","));
867 
868  ASSERTL0(tmp.size() == 2, "periodic pairs ill-defined");
869 
870  vector<unsigned> data(2);
871  data[0] = boost::lexical_cast<unsigned>(tmp[0]);
872  data[1] = boost::lexical_cast<unsigned>(tmp[1]);
873 
874  ASSERTL0(!periodic.count(data[0]), "curve already periodic");
875  ASSERTL0(!periodic.count(data[1]), "curve already periodic");
876 
877  m_periodicPairs[data[0]] = data[1];
878  periodic.insert(data[0]);
879  periodic.insert(data[1]);
880  }
881 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::map< unsigned, unsigned > m_periodicPairs
map of periodic curve pairs
Definition: 2DGenerator.h:85
std::map< std::string, ConfigOption > m_config
List of configuration values.

◆ Process()

void Nektar::NekMeshUtils::Generator2D::Process ( )
virtual

Implements Nektar::NekMeshUtils::Module.

Definition at line 81 of file 2DGenerator.cpp.

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), ASSERTL0, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::LibUtilities::Interpreter::DefineFunction(), Nektar::LibUtilities::eSegment, Nektar::LibUtilities::Interpreter::Evaluate(), Nektar::StdRegions::find(), FindBLEnds(), Nektar::ParseUtils::GenerateSeqVector(), Nektar::NekMeshUtils::GetElementFactory(), CG_Iterations::loc, m_blCurves, m_blends, Nektar::NekMeshUtils::Module::m_config, m_curvemeshes, m_facemeshes, Nektar::NekMeshUtils::Module::m_mesh, m_thickness, m_thickness_ID, MakeBL(), MakeBLPrep(), MakePeriodic(), PeriodicPrep(), Nektar::LibUtilities::PrintProgressbar(), Nektar::NekMeshUtils::Module::ProcessComposites(), Nektar::NekMeshUtils::Module::ProcessEdges(), Nektar::NekMeshUtils::Module::ProcessElements(), Nektar::NekMeshUtils::Module::ProcessFaces(), Nektar::NekMeshUtils::Module::ProcessVertices(), and Report().

82 {
83  // Check that cad is 2D
84  Array<OneD, NekDouble> bndBox = m_mesh->m_cad->GetBoundingBox();
85  ASSERTL0(fabs(bndBox[5] - bndBox[4]) < 1.0e-7, "CAD isn't 2D");
86 
87  if (m_mesh->m_verbose)
88  {
89  cout << endl << "2D meshing" << endl;
90  cout << endl << "\tCurve meshing:" << endl << endl;
91  }
92  m_mesh->m_numNodes = m_mesh->m_cad->GetNumVerts();
94  m_thickness.DefineFunction("x y z", m_config["blthick"].as<string>());
95  ParseUtils::GenerateSeqVector(m_config["blcurves"].as<string>(),
96  m_blCurves);
97 
98  // find the ends of the BL curves
99  if (m_config["blcurves"].beenSet)
100  {
101  FindBLEnds();
102  }
103 
104  // linear mesh all curves
105  for (int i = 1; i <= m_mesh->m_cad->GetNumCurve(); i++)
106  {
107  if (m_mesh->m_verbose)
108  {
109  LibUtilities::PrintProgressbar(i, m_mesh->m_cad->GetNumCurve(),
110  "Curve progress");
111  }
112  vector<unsigned int>::iterator f =
113  find(m_blCurves.begin(), m_blCurves.end(), i);
114  if (f == m_blCurves.end())
115  {
116  m_curvemeshes[i] =
118 
119  // Fheck if this curve is at an end of the BL
120  // If so, define an offset for the second node, corresponding to the
121  // BL thickness
122  if (m_blends.count(i))
123  {
124  vector<CADVertSharedPtr> vertices =
125  m_mesh->m_cad->GetCurve(i)->GetVertex();
126  Array<OneD, NekDouble> loc;
127  NekDouble t;
128 
129  // offset needed at first node (or both)
130  if (m_blends[i] == 0 || m_blends[i] == 2)
131  {
132  loc = vertices[0]->GetLoc();
133  t = m_thickness.Evaluate(m_thickness_ID, loc[0], loc[1],
134  loc[2], 0.0);
135  m_curvemeshes[i]->SetOffset(0, t);
136  }
137  // offset needed at second node (or both)
138  if (m_blends[i] == 1 || m_blends[i] == 2)
139  {
140  loc = vertices[1]->GetLoc();
141  t = m_thickness.Evaluate(m_thickness_ID, loc[0], loc[1],
142  loc[2], 0.0);
143  m_curvemeshes[i]->SetOffset(1, t);
144  }
145  }
146  }
147  else
148  {
150  i, m_mesh, m_config["blthick"].as<string>());
151  }
152  m_curvemeshes[i]->Mesh();
153  }
154 
155  ////////
156  // consider periodic curves
157 
158  if (m_config["periodic"].beenSet)
159  {
160  PeriodicPrep();
161  MakePeriodic();
162  }
163 
164  ////////////////////////////////////////
165 
166  if (m_config["blcurves"].beenSet)
167  {
168  // we need to do the boundary layer generation in a face by face basis
169  MakeBLPrep();
170  for (int i = 1; i <= m_mesh->m_cad->GetNumSurf(); i++)
171  {
172  MakeBL(i);
173  }
174 
175  // If the BL doesn't form closed loops, we need to remove the outside
176  // nodes from the curve meshes
177  for (auto &ic : m_blends)
178  {
179  vector<NodeSharedPtr> nodes =
180  m_curvemeshes[ic.first]->GetMeshPoints();
181 
182  if (ic.second == 0 || ic.second == 2)
183  {
184  nodes.erase(nodes.begin());
185  }
186  if (ic.second == 1 || ic.second == 2)
187  {
188  nodes.erase(nodes.end() - 1);
189  }
190 
191  // Rebuild the curvemesh without the first node, the last node or
192  // both
193  m_curvemeshes[ic.first] =
195  nodes);
196  }
197  }
198 
199  if (m_mesh->m_verbose)
200  {
201  cout << endl << "\tFace meshing:" << endl << endl;
202  }
203  // linear mesh all surfaces
204  for (int i = 1; i <= m_mesh->m_cad->GetNumSurf(); i++)
205  {
206  if (m_mesh->m_verbose)
207  {
208  LibUtilities::PrintProgressbar(i, m_mesh->m_cad->GetNumSurf(),
209  "Face progress");
210  }
211 
213  i, m_mesh, m_curvemeshes, 99 + i);
214  m_facemeshes[i]->Mesh();
215  }
216 
217  ////////////////////////////////////
218 
219  EdgeSet::iterator it;
220  for (auto &it : m_mesh->m_edgeSet)
221  {
222  vector<NodeSharedPtr> ns;
223  ns.push_back(it->m_n1);
224  ns.push_back(it->m_n2);
225  // for each iterator create a LibUtilities::eSegement
226  // push segment into m_mesh->m_element[1]
227  // tag for the elements shoudl be the CAD number of the curves
228  ElmtConfig conf(LibUtilities::eSegment, 1, false, false);
229  vector<int> tags;
230  tags.push_back(it->m_parentCAD->GetId());
232  LibUtilities::eSegment, conf, ns, tags);
233  m_mesh->m_element[1].push_back(E2);
234  }
235 
236  ProcessVertices();
237  ProcessEdges();
238  ProcessFaces();
239  ProcessElements();
241  Report();
242 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
int PrintProgressbar(const int position, const int goal, const std::string message, int lastprogress=-1)
Prints a progressbar.
Definition: Progressbar.hpp:67
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
std::vector< unsigned int > m_blCurves
list of curves needing a BL
Definition: 2DGenerator.h:87
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
std::map< int, FaceMeshSharedPtr > m_facemeshes
map of individual surface meshes from parametric surfaces
Definition: 2DGenerator.h:81
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
std::map< unsigned, unsigned > m_blends
map of curves and Bl ends: 0, 1 or 2 (for both)
Definition: 2DGenerator.h:89
int m_thickness_ID
BL thickness expression ID.
Definition: 2DGenerator.h:95
LibUtilities::Interpreter m_thickness
BL thickness expression.
Definition: 2DGenerator.h:93
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
virtual NEKMESHUTILS_EXPORT void ProcessFaces(bool ReprocessFaces=true)
Extract element faces.
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
double NekDouble
std::map< std::string, ConfigOption > m_config
List of configuration values.
virtual NEKMESHUTILS_EXPORT void ProcessVertices()
Extract element vertices.
virtual NEKMESHUTILS_EXPORT void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
Definition: StdRegions.hpp:358
std::map< int, CurveMeshSharedPtr > m_curvemeshes
map of individual curve meshes of the curves in the domain
Definition: 2DGenerator.h:83
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector. ...
Definition: ParseUtils.cpp:108

◆ Report()

void Nektar::NekMeshUtils::Generator2D::Report ( )
private

Definition at line 903 of file 2DGenerator.cpp.

References Nektar::NekMeshUtils::Module::m_mesh.

Referenced by Process().

904 {
905  if (m_mesh->m_verbose)
906  {
907  int ns = m_mesh->m_vertexSet.size();
908  int es = m_mesh->m_edgeSet.size();
909  int ts = m_mesh->m_element[2].size();
910  int ep = ns - es + ts;
911  cout << endl << "\tSurface mesh statistics" << endl;
912  cout << "\t\tNodes: " << ns << endl;
913  cout << "\t\tEdges: " << es << endl;
914  cout << "\t\tTriangles " << ts << endl;
915  cout << "\t\tEuler-PoincarĂ© characteristic: " << ep << endl;
916  }
917 }

Member Data Documentation

◆ className

ModuleKey Nektar::NekMeshUtils::Generator2D::className
static
Initial value:

Definition at line 60 of file 2DGenerator.h.

◆ m_blCurves

std::vector<unsigned int> Nektar::NekMeshUtils::Generator2D::m_blCurves
private

list of curves needing a BL

Definition at line 87 of file 2DGenerator.h.

Referenced by FindBLEnds(), MakeBL(), MakeBLPrep(), and Process().

◆ m_blEdges

std::vector<EdgeSharedPtr> Nektar::NekMeshUtils::Generator2D::m_blEdges
private

list of BL edges

Definition at line 91 of file 2DGenerator.h.

Referenced by MakeBL(), and MakeBLPrep().

◆ m_blends

std::map<unsigned, unsigned> Nektar::NekMeshUtils::Generator2D::m_blends
private

map of curves and Bl ends: 0, 1 or 2 (for both)

Definition at line 89 of file 2DGenerator.h.

Referenced by FindBLEnds(), and Process().

◆ m_curvemeshes

std::map<int, CurveMeshSharedPtr> Nektar::NekMeshUtils::Generator2D::m_curvemeshes
private

map of individual curve meshes of the curves in the domain

Definition at line 83 of file 2DGenerator.h.

Referenced by MakeBL(), MakeBLPrep(), MakePeriodic(), and Process().

◆ m_facemeshes

std::map<int, FaceMeshSharedPtr> Nektar::NekMeshUtils::Generator2D::m_facemeshes
private

map of individual surface meshes from parametric surfaces

Definition at line 81 of file 2DGenerator.h.

Referenced by Process().

◆ m_nodesToEdge

std::map<NodeSharedPtr, std::vector<EdgeSharedPtr> > Nektar::NekMeshUtils::Generator2D::m_nodesToEdge
private

map of BL curve nodes to adjacent edges

Definition at line 97 of file 2DGenerator.h.

Referenced by MakeBL(), and MakeBLPrep().

◆ m_periodicPairs

std::map<unsigned, unsigned> Nektar::NekMeshUtils::Generator2D::m_periodicPairs
private

map of periodic curve pairs

Definition at line 85 of file 2DGenerator.h.

Referenced by MakePeriodic(), and PeriodicPrep().

◆ m_thickness

LibUtilities::Interpreter Nektar::NekMeshUtils::Generator2D::m_thickness
private

BL thickness expression.

Definition at line 93 of file 2DGenerator.h.

Referenced by MakeBL(), and Process().

◆ m_thickness_ID

int Nektar::NekMeshUtils::Generator2D::m_thickness_ID
private

BL thickness expression ID.

Definition at line 95 of file 2DGenerator.h.

Referenced by MakeBL(), and Process().