Nektar++
Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
Nektar::Utilities::ProcessExtractSurf Class Reference

This processing module calculates the Jacobian of elements using SpatialDomains::GeomFactors and the Element::GetGeom method. For now it simply prints a list of elements which have negative Jacobian. More...

#include <ProcessExtractSurf.h>

Inheritance diagram for Nektar::Utilities::ProcessExtractSurf:
[legend]

Public Member Functions

 ProcessExtractSurf (NekMeshUtils::MeshSharedPtr m)
 
virtual ~ProcessExtractSurf ()
 
virtual void Process ()
 Write mesh to output file. More...
 
- 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 (NekMeshUtils::MeshSharedPtr m)
 Creates an instance of this class. More...
 

Static Public Attributes

static NekMeshUtils::ModuleKey className
 

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

This processing module calculates the Jacobian of elements using SpatialDomains::GeomFactors and the Element::GetGeom method. For now it simply prints a list of elements which have negative Jacobian.

Definition at line 51 of file ProcessExtractSurf.h.

Constructor & Destructor Documentation

◆ ProcessExtractSurf()

Nektar::Utilities::ProcessExtractSurf::ProcessExtractSurf ( NekMeshUtils::MeshSharedPtr  m)

Definition at line 53 of file ProcessExtractSurf.cpp.

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

53  : ProcessModule(m)
54 {
55  m_config["surf"] = ConfigOption(
56  false, "NotSet", "Tag identifying surface/composite to process.");
57  m_config["detectbnd"] =
58  ConfigOption(false, "-1", "Tag to detect on boundary composites");
59 }
Represents a command-line configuration option.
NEKMESHUTILS_EXPORT ProcessModule(MeshSharedPtr p_m)
std::map< std::string, ConfigOption > m_config
List of configuration values.

◆ ~ProcessExtractSurf()

Nektar::Utilities::ProcessExtractSurf::~ProcessExtractSurf ( )
virtual

Definition at line 61 of file ProcessExtractSurf.cpp.

62 {
63 }

Member Function Documentation

◆ create()

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

Creates an instance of this class.

Definition at line 55 of file ProcessExtractSurf.h.

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

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

◆ Process()

void Nektar::Utilities::ProcessExtractSurf::Process ( )
virtual

Write mesh to output file.

Implements Nektar::NekMeshUtils::Module.

Definition at line 65 of file ProcessExtractSurf.cpp.

References ASSERTL0, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::LibUtilities::eSegment, Nektar::ParseUtils::GenerateSeqVector(), Nektar::NekMeshUtils::GetElementFactory(), Nektar::NekMeshUtils::Module::m_config, and Nektar::NekMeshUtils::Module::m_mesh.

66 {
67  int i, j;
68  string surf = m_config["surf"].as<string>();
69  bool detectbnd = m_config["detectbnd"].beenSet;
70 
71  // Obtain vector of surface IDs from string.
72  vector<unsigned int> surfs;
74  "Failed to interp surf string. Have you specified this string?");
75  sort(surfs.begin(), surfs.end());
76 
77  // If we're running in verbose mode print out a list of surfaces.
78  if (m_mesh->m_verbose)
79  {
80  cout << "ProcessExtractSurf: extracting surface"
81  << (surfs.size() > 1 ? "s" : "") << " " << surf << endl;
82  }
83 
84  // Make a copy of all existing elements of one dimension lower.
85  vector<ElementSharedPtr> el = m_mesh->m_element[m_mesh->m_expDim - 1];
86 
87  // Clear all elements.
88  m_mesh->m_element[m_mesh->m_expDim].clear();
89  m_mesh->m_element[m_mesh->m_expDim - 1].clear();
90 
91  // Clear existing vertices, edges and faces.
92  m_mesh->m_vertexSet.clear();
93 
94  m_mesh->m_edgeSet.clear();
95  m_mesh->m_faceSet.clear();
96 
97  // Clear all edge -> element links.
98  for (i = 0; i < el.size(); ++i)
99  {
100  vector<EdgeSharedPtr> edges = el[i]->GetEdgeList();
101  for (j = 0; j < edges.size(); ++j)
102  {
103  edges[j]->m_elLink.clear();
104  }
105 
106  FaceSharedPtr f = el[i]->GetFaceLink();
107  if (f)
108  {
109  for (j = 0; j < f->m_edgeList.size(); ++j)
110  {
111  f->m_edgeList[j]->m_elLink.clear();
112  }
113  }
114  }
115 
116  // keptIds stores IDs of elements we processed earlier.
117  std::unordered_set<int> keptIds;
118 
119  EdgeSet bndEdgeSet;
120 
121  // Iterate over list of surface elements.
122  for (i = 0; i < el.size(); ++i)
123  {
124  // Work out whether this lies on our surface of interest.
125  vector<int> inter, tags = el[i]->GetTagList();
126 
127  sort(tags.begin(), tags.end());
128  set_intersection(surfs.begin(),
129  surfs.end(),
130  tags.begin(),
131  tags.end(),
132  back_inserter(inter));
133 
134  // It doesn't continue to next element.
135  if (inter.size() != 1)
136  {
137  continue;
138  }
139 
140  // Get list of element vertices and edges.
141  ElementSharedPtr elmt = el[i];
142  vector<NodeSharedPtr> verts = elmt->GetVertexList();
143  vector<EdgeSharedPtr> edges = elmt->GetEdgeList();
144 
145  // Insert surface vertices.
146  for (j = 0; j < verts.size(); ++j)
147  {
148  m_mesh->m_vertexSet.insert(verts[j]);
149  }
150 
151  // Problem: edges and element IDs aren't enumerated with
152  // geometry IDs by some input modules/the Module ProcessEdges
153  // function. Get around this by replacing everything in the
154  // edge/face with information from edge/face link.
155  EdgeSharedPtr e = elmt->GetEdgeLink();
156  FaceSharedPtr f = elmt->GetFaceLink();
157  if (e)
158  {
159  elmt->SetId(e->m_id);
160  }
161  else if (f)
162  {
163  for (j = 0; j < f->m_vertexList.size(); j++)
164  {
165  elmt->SetVertex(j, f->m_vertexList[j]);
166  }
167 
168  for (j = 0; j < edges.size(); ++j)
169  {
170  m_mesh->m_edgeSet.insert(f->m_edgeList[j]);
171  elmt->SetEdge(j, f->m_edgeList[j]);
172  f->m_edgeList[j]->m_elLink.push_back(std::make_pair(elmt, j));
173 
174  // generate a list of edges on boundary of surfaces being
175  // extracted
176  auto edit = bndEdgeSet.find(f->m_edgeList[j]);
177  if (edit != bndEdgeSet.end())
178  {
179  // remove since visited more than once
180  bndEdgeSet.erase(edit);
181  }
182  else
183  {
184  bndEdgeSet.insert(f->m_edgeList[j]);
185  }
186  }
187  elmt->SetVolumeNodes(f->m_faceNodes);
188  elmt->SetId(f->m_id);
189  elmt->SetCurveType(f->m_curveType);
190  }
191  else
192  {
193  for (j = 0; j < edges.size(); ++j)
194  {
195  m_mesh->m_edgeSet.insert(edges[j]);
196  }
197  }
198 
199  // Nullify edge/face links to get correct tag
200  elmt->SetFaceLink(FaceSharedPtr());
201  elmt->SetEdgeLink(EdgeSharedPtr());
202  keptIds.insert(elmt->GetId());
203 
204  // Push element back into the list.
205  m_mesh->m_element[m_mesh->m_expDim - 1].push_back(elmt);
206  }
207 
208  // Decrement the expansion dimension to get manifold embedding.
209  m_mesh->m_expDim--;
210 
211  // Now process composites. This is necessary because 2D surfaces may
212  // contain both quadrilaterals and triangles and so need to be split
213  // up.
214  CompositeMap tmp = m_mesh->m_composite;
215 
216  m_mesh->m_composite.clear();
217  int maxId = -1;
218 
219  // Loop over composites for first time to determine any composites
220  // which don't have elements of the correct dimension.
221  for (auto &it : tmp)
222  {
223  if (it.second->m_items[0]->GetDim() != m_mesh->m_expDim)
224  {
225  continue;
226  }
227 
228  vector<ElementSharedPtr> el = it.second->m_items;
229  it.second->m_items.clear();
230 
231  for (i = 0; i < el.size(); ++i)
232  {
233  if (keptIds.count(el[i]->GetId()) > 0)
234  {
235  it.second->m_items.push_back(el[i]);
236  }
237  }
238 
239  if (it.second->m_items.size() == 0)
240  {
241  continue;
242  }
243 
244  m_mesh->m_composite.insert(it);
245 
246  // Figure out the maximum ID so if we need to create new
247  // composites we can give them a unique ID.
248  maxId = (std::max)(maxId, (int)it.second->m_id) + 1;
249  }
250 
251  tmp = m_mesh->m_composite;
252  m_mesh->m_composite.clear();
253 
254  // Now do another loop over the composites to remove composites
255  // which don't contain any elements in the new mesh.
256  for (auto &it : tmp)
257  {
258  CompositeSharedPtr c = it.second;
259  vector<ElementSharedPtr> el = c->m_items;
260 
261  // Remove all but the first element from this composite.
262  string initialTag = el[0]->GetTag();
263  c->m_items.resize(1);
264  c->m_tag = initialTag;
265 
266  // newComps stores the new composites. The key is the composite
267  // type (e.g. Q for quad) and value is the composite.
268  map<string, CompositeSharedPtr> newComps;
269  newComps[initialTag] = c;
270 
271  // Loop over remaining elements in composite and figure out
272  // whether it needs to be split up.
273  for (i = 1; i < el.size(); ++i)
274  {
275  // See if tag exists. If it does, we append this to the
276  // composite, otherwise we create a new composite and store
277  // it in newComps.
278  string tag = el[i]->GetTag();
279  auto it2 = newComps.find(tag);
280  if (it2 == newComps.end())
281  {
282  CompositeSharedPtr newComp(new Composite());
283  newComp->m_id = maxId++;
284  newComp->m_tag = tag;
285  newComp->m_items.push_back(el[i]);
286  newComps[tag] = newComp;
287  }
288  else
289  {
290  it2->second->m_items.push_back(el[i]);
291  }
292  }
293 
294  // Print out mapping information if we remapped composite IDs.
295  if (m_mesh->m_verbose && newComps.size() > 1)
296  {
297  cout << "- Mapping composite " << it.first << " ->";
298  }
299 
300  // Insert new composites.
301  i = 0;
302  for (auto &it2 : newComps)
303  {
304  if (m_mesh->m_verbose && newComps.size() > 1)
305  {
306  cout << (i > 0 ? ", " : " ") << it2.second->m_id << "("
307  << it2.second->m_tag << ")";
308  }
309  m_mesh->m_composite[it2.second->m_id] = it2.second;
310  ++i;
311  }
312 
313  if (m_mesh->m_verbose && newComps.size() > 1)
314  {
315  cout << endl;
316  }
317  }
318 
319  // Detect composites for boundaries. This is done by looping over all
320  // elements identifiying if they are not part of required surfaces and if
321  // not setting up a list of boundary edges (identified by only being visited
322  // once). This list is then compared against an earlier identification of
323  // boundary edges on the required surfaces and if the two overlap add a
324  // segment element and put segment element in composite as well
325  if (detectbnd)
326  {
327  if (m_mesh->m_expDim != 2)
328  {
329  cerr << "Surface boundary detection only implemented for 2D meshes"
330  << endl;
331  return;
332  }
333 
334  map<int, EdgeSet> surfBndEdgeSet;
335  map<int, string> surfLabels;
336 
337  // Iterate over list of surface elements.
338  for (i = 0; i < el.size(); ++i)
339  {
340  // Work out whether this lies on our surface of interest.
341  vector<int> inter, tags = el[i]->GetTagList();
342 
343  ASSERTL0(tags.size() == 1, "Not sure what mutliple tags implies");
344 
345  sort(tags.begin(), tags.end());
346  set_intersection(surfs.begin(),
347  surfs.end(),
348  tags.begin(),
349  tags.end(),
350  back_inserter(inter));
351 
352  // It does so continue to next element.
353  if (inter.size() == 1)
354  {
355  continue;
356  }
357 
358  int surf = tags[0];
359 
360  // gather surface labels if they exist.
361  if (m_mesh->m_faceLabels.count(surf))
362  {
363  surfLabels[surf] = m_mesh->m_faceLabels[surf];
364  }
365 
366  // Get list of element vertices and edges.
367  ElementSharedPtr elmt = el[i];
368  vector<EdgeSharedPtr> edges = elmt->GetEdgeList();
369 
370  FaceSharedPtr f = elmt->GetFaceLink();
371  if (f)
372  {
373  for (j = 0; j < edges.size(); ++j)
374  {
375  // generate a list of edges on boundary of surfaces being
376  // extracted
377  if (surfBndEdgeSet.count(surf))
378  {
379  auto edit = surfBndEdgeSet[surf].find(f->m_edgeList[j]);
380  if (edit != surfBndEdgeSet[surf].end())
381  {
382  // remove since visited more than once
383  surfBndEdgeSet[surf].erase(edit);
384  }
385  else
386  {
387  surfBndEdgeSet[surf].insert(f->m_edgeList[j]);
388  }
389  }
390  else
391  {
392  EdgeSet newEdgeSet;
393  surfBndEdgeSet[surf] = newEdgeSet;
394  surfBndEdgeSet[surf].insert(f->m_edgeList[j]);
395  }
396  }
397  }
398  }
399 
400  m_mesh->m_faceLabels.clear();
401 
402  // iteratve over surfBndEdgeSet and see if they are in BndEdgeSet
403  for (auto &esetit : surfBndEdgeSet)
404  {
405  CompositeSharedPtr newComp(new Composite());
406  newComp->m_id = maxId;
407  newComp->m_tag = "E";
408  // set up labels if they exist
409  if (surfLabels.count(esetit.first))
410  {
411  newComp->m_label = surfLabels[esetit.first];
412  }
413 
414  for (auto &edit : esetit.second)
415  {
416  auto locit = bndEdgeSet.find(edit);
417  if (locit != bndEdgeSet.end())
418  {
419  // make 1D segment element
421 
422  vector<int> tags;
423  tags.push_back(maxId);
424 
425  // make unique node list
426  vector<NodeSharedPtr> nodeList;
427  nodeList.push_back((*locit)->m_n1);
428  nodeList.push_back((*locit)->m_n2);
429 
430  ElmtConfig conf(elType, 1, true, true);
432  elType, conf, nodeList, tags);
433  E->SetId((*locit)->m_id);
434  m_mesh->m_element[E->GetDim()].push_back(E);
435  newComp->m_items.push_back(E);
436  }
437  }
438 
439  if (newComp->m_items.size())
440  {
441  m_mesh->m_composite[maxId++] = newComp;
442  }
443  }
444  }
445 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Basic information about an element.
Definition: ElementConfig.h:49
std::unordered_set< EdgeSharedPtr, EdgeHash > EdgeSet
Definition: Edge.h:159
std::map< unsigned int, CompositeSharedPtr > CompositeMap
Container of composites; key is the composite id, value is the composite.
Definition: Composite.h:73
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
std::shared_ptr< Face > FaceSharedPtr
Definition: Face.h:155
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
A composite is a collection of elements.
Definition: Composite.h:50
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
std::map< std::string, ConfigOption > m_config
List of configuration values.
std::shared_ptr< Composite > CompositeSharedPtr
Shared pointer to a composite.
Definition: Composite.h:70
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

Member Data Documentation

◆ className

ModuleKey Nektar::Utilities::ProcessExtractSurf::className
static
Initial value:
=
"Process elements to extract a specified surface(s) or composites(s).")

Definition at line 59 of file ProcessExtractSurf.h.