Nektar++
ProcessDetectSurf.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: ProcessDetectSurf.cpp
4 //
5 // For more information, please see: http://www.nektar.info/
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Extract one or more surfaces from mesh.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
37 #include "ProcessDetectSurf.h"
38 
39 using namespace std;
40 using namespace Nektar::NekMeshUtils;
41 
42 namespace Nektar
43 {
44 namespace Utilities
45 {
46 
47 ModuleKey ProcessDetectSurf::className =
49  ModuleKey(eProcessModule, "detect"),
50  ProcessDetectSurf::create,
51  "Process elements to detect a surface.");
52 
53 ProcessDetectSurf::ProcessDetectSurf(MeshSharedPtr m) : ProcessModule(m)
54 {
55  m_config["vol"] =
56  ConfigOption(false, "-1", "Tag identifying surface to process.");
57 }
58 
60 {
61 }
62 
63 struct EdgeInfo
64 {
65  EdgeInfo() : count(0)
66  {
67  }
68  int count;
70  unsigned int group;
71 };
72 
74 {
75  if (m_mesh->m_expDim > 2)
76  {
77  cerr << "Surface detection only implemented for 2D meshes" << endl;
78  return;
79  }
80 
81  int i, j;
82  string surf = m_config["vol"].as<string>();
83 
84  // Obtain vector of surface IDs from string.
85  vector<unsigned int> surfs;
86  if (surf != "-1")
87  {
88  ParseUtils::GenerateSeqVector(surf, surfs);
89  sort(surfs.begin(), surfs.end());
90  }
91 
92  // If we're running in verbose mode print out a list of surfaces.
93  if (m_mesh->m_verbose)
94  {
95  cout << "ProcessDetectSurf: detecting surfaces";
96  if (surfs.size() > 0)
97  {
98  cout << " for surface" << (surfs.size() == 1 ? "" : "s") << " "
99  << surf << endl;
100  }
101  }
102 
103  vector<ElementSharedPtr> &el = m_mesh->m_element[m_mesh->m_expDim];
104  map<int, EdgeInfo> edgeCount;
105  set<int> doneIds;
106  map<int, int> idMap;
107 
108  // Iterate over list of surface elements.
109  for (i = 0; i < el.size(); ++i)
110  {
111  // Work out whether this lies on our surface of interest.
112  if (surfs.size() > 0)
113  {
114  vector<int> inter, tags = el[i]->GetTagList();
115 
116  sort(tags.begin(), tags.end());
117  set_intersection(surfs.begin(),
118  surfs.end(),
119  tags.begin(),
120  tags.end(),
121  back_inserter(inter));
122 
123  // It doesn't continue to next element.
124  if (inter.size() != 1)
125  {
126  continue;
127  }
128  }
129 
130  // List all edges.
131  ElementSharedPtr elmt = el[i];
132  for (j = 0; j < elmt->GetEdgeCount(); ++j)
133  {
134  EdgeSharedPtr e = elmt->GetEdge(j);
135  int eId = e->m_id;
136  edgeCount[eId].count++;
137  edgeCount[eId].edge = e;
138  }
139 
140  doneIds.insert(elmt->GetId());
141  ASSERTL0(idMap.count(elmt->GetId()) == 0, "Shouldn't happen");
142  idMap[elmt->GetId()] = i;
143  }
144 
145  unsigned int maxId = 0;
146 
147  for (auto &cIt : m_mesh->m_composite)
148  {
149  maxId = (std::max)(cIt.first, maxId);
150  }
151 
152  ++maxId;
153 
154  while (doneIds.size() > 0)
155  {
156  ElementSharedPtr start =
157  m_mesh->m_element[m_mesh->m_expDim][idMap[*(doneIds.begin())]];
158 
159  vector<ElementSharedPtr> block;
160  FindContiguousSurface(start, doneIds, block);
161  ASSERTL0(block.size() > 0, "Contiguous block not found");
162 
163  // Loop over all edges in block.
164  for (i = 0; i < block.size(); ++i)
165  {
166  // Find edge info.
167  ElementSharedPtr elmt = block[i];
168 
169  for (j = 0; j < elmt->GetEdgeCount(); ++j)
170  {
171  auto eIt = edgeCount.find(elmt->GetEdge(j)->m_id);
172  ASSERTL0(eIt != edgeCount.end(), "Couldn't find edge");
173  eIt->second.group = maxId;
174  }
175  }
176 
177  ++maxId;
178  }
179 
180  for (auto &eIt : edgeCount)
181  {
182  if (eIt.second.count > 1)
183  {
184  continue;
185  }
186 
187  unsigned int compId = eIt.second.group;
188  auto cIt = m_mesh->m_composite.find(compId);
189 
190  if (cIt == m_mesh->m_composite.end())
191  {
192  CompositeSharedPtr comp(new Composite());
193  comp->m_id = compId;
194  comp->m_tag = "E";
195  cIt =
196  m_mesh->m_composite.insert(std::make_pair(compId, comp)).first;
197  }
198 
199  vector<int> tags(1);
200  tags[0] = compId;
201  vector<NodeSharedPtr> nodeList(2);
202  nodeList[0] = eIt.second.edge->m_n1;
203  nodeList[1] = eIt.second.edge->m_n2;
204 
205  ElmtConfig conf(LibUtilities::eSegment, 1, false, false);
207  LibUtilities::eSegment, conf, nodeList, tags);
208  elmt->SetEdgeLink(eIt.second.edge);
209 
210  cIt->second->m_items.push_back(elmt);
211  }
212 }
213 
215  set<int> &doneIds,
216  vector<ElementSharedPtr> &block)
217 {
218  block.push_back(start);
219  doneIds.erase(start->GetId());
220 
221  vector<EdgeSharedPtr> edges = start->GetEdgeList();
222 
223  for (int i = 0; i < edges.size(); ++i)
224  {
225  for (int j = 0; j < edges[i]->m_elLink.size(); ++j)
226  {
227  ElementSharedPtr elmt = edges[i]->m_elLink[j].first;
228  if (elmt == start)
229  {
230  continue;
231  }
232 
233  if (doneIds.count(elmt->GetId()) == 0)
234  {
235  continue;
236  }
237 
238  FindContiguousSurface(elmt, doneIds, block);
239  }
240  }
241 }
242 }
243 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
void FindContiguousSurface(NekMeshUtils::ElementSharedPtr start, std::set< int > &doneIds, std::vector< NekMeshUtils::ElementSharedPtr > &block)
Basic information about an element.
Definition: ElementConfig.h:49
STL namespace.
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
Definition: Edge.h:136
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Definition: Mesh.h:156
ElementFactory & GetElementFactory()
Definition: Element.cpp:44
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::pair< ModuleType, std::string > ModuleKey
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
Represents a command-line configuration option.
virtual void Process()
Write mesh to output file.
std::map< std::string, ConfigOption > m_config
List of configuration values.
Abstract base class for processing modules.
std::shared_ptr< Composite > CompositeSharedPtr
Shared pointer to a composite.
Definition: Composite.h:70
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
std::pair< ModuleType, std::string > ModuleKey
ModuleFactory & GetModuleFactory()
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