Nektar++
CFIMesh.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: SurfaceMeshing.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: surfacemeshing object methods.
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
35 #include "CFIMesh.h"
36 
40 
41 using namespace std;
42 namespace Nektar
43 {
44 namespace NekMeshUtils
45 {
46 
48  ModuleKey(eProcessModule, "cfimesh"), CFIMesh::create,
49  "Extracts mesh from cfi");
50 
51 CFIMesh::CFIMesh(MeshSharedPtr m) : ProcessModule(m)
52 {
53 }
54 
56 {
57 }
58 
60 {
61  if (m_mesh->m_verbose)
62  {
63  cout << endl << "Loading mesh from CFI" << endl;
64  }
65 
66  m_mesh->m_expDim = 3;
67  m_mesh->m_spaceDim = 3;
68 
69  m_cad = std::dynamic_pointer_cast<CADSystemCFI>(m_mesh->m_cad);
70  m_nameToCurveId = m_cad->GetCFICurveId();
71  m_nameToFaceId = m_cad->GetCFIFaceId();
72  m_nameToVertId = m_cad->GetCFIVertId();
73  m_model = m_cad->GetCFIModel();
74  NekDouble scal = m_cad->GetScaling();
75 
76  map<int, NodeSharedPtr> nodes;
77  vector<cfi::NodeDefinition> *cfinodes = m_model->getFenodes();
78 
79  if (m_mesh->m_verbose)
80  {
81  cout << "Nodes " << cfinodes->size() << endl;
82  }
83 
84  // filter all mesh nodes into a indexed map and project to CAD
85  for (auto &it : *cfinodes)
86  {
88  cfi::Position ps = it.node->getXYZ();
89  xyz[0] = ps.x * scal;
90  xyz[1] = ps.y * scal;
91  xyz[2] = ps.z * scal;
92  int id = it.node->number;
93 
94  NodeSharedPtr n =
95  std::shared_ptr<Node>(new Node(id, xyz[0], xyz[1], xyz[2]));
96  nodes.insert(pair<int, NodeSharedPtr>(id, n));
97 
98  // point built now add cad if needed
99  cfi::MeshableEntity *p = it.parent;
100 
101  if (p->type == cfi::TYPE_LINE)
102  {
103  auto f = m_nameToCurveId.find(p->getName());
104  if (f != m_nameToCurveId.end())
105  {
106  CADCurveSharedPtr c = m_mesh->m_cad->GetCurve(f->second);
107  NekDouble t;
108  c->loct(xyz, t);
109  n->SetCADCurve(c, t);
110 
111  vector<pair<CADSurfSharedPtr, CADOrientation::Orientation>> ss =
112  c->GetAdjSurf();
113  for (int j = 0; j < ss.size(); j++)
114  {
115  Array<OneD, NekDouble> uv = ss[j].first->locuv(xyz);
116  n->SetCADSurf(ss[j].first, uv);
117  }
118  }
119  }
120  else if (p->type == cfi::TYPE_FACE)
121  {
122  auto f = m_nameToFaceId.find(p->getName());
123  if (f != m_nameToFaceId.end())
124  {
125  CADSurfSharedPtr s = m_mesh->m_cad->GetSurf(f->second);
126  Array<OneD, NekDouble> uv = s->locuv(xyz);
127  n->SetCADSurf(s, uv);
128  }
129  }
130  else if (p->type == cfi::TYPE_POINT)
131  {
132  auto f = m_nameToVertId.find(p->getName());
133  if (f != m_nameToVertId.end())
134  {
135  CADVertSharedPtr v = m_mesh->m_cad->GetVert(f->second);
136  vector<CADCurveSharedPtr> cs = v->GetAdjCurves();
137  for (int i = 0; i < cs.size(); i++)
138  {
139  NekDouble t;
140  cs[i]->loct(xyz, t);
141  n->SetCADCurve(cs[i], t);
142  vector<pair<CADSurfSharedPtr, CADOrientation::Orientation>>
143  ss = cs[i]->GetAdjSurf();
144  for (int j = 0; j < ss.size(); j++)
145  {
146  Array<OneD, NekDouble> uv = ss[j].first->locuv(xyz);
147  n->SetCADSurf(ss[j].first, uv);
148  }
149  }
150  }
151  }
152  }
153 
154  ////
155  // Really important fact. Nodes must be renumbered as they are read by the
156  // elements
157  // such that vertical edges on the prism are sequential
158  // In doing so we ensure the orienation will work
159  // we dont want to renumber nodes that have already been numbered, hence the
160  // set
161  // the set will be tacked by the cfiID as that is a constant
162 
163  map<int, set<LibUtilities::ShapeType>> cfiIdToTypes;
164 
165  vector<cfi::ElementDefinition> *prisms =
166  m_model->getElements(cfi::SUBTYPE_PE6, 6);
167  for (auto &it : *prisms)
168  {
169  vector<cfi::Node *> ns = it.nodes;
170  for (int i = 0; i < ns.size(); i++)
171  {
172  cfiIdToTypes[ns[i]->number].insert(LibUtilities::ePrism);
173  }
174  }
175  vector<cfi::ElementDefinition> *hexs =
176  m_model->getElements(cfi::SUBTYPE_HE8, 8);
177  for (auto &it : *hexs)
178  {
179  vector<cfi::Node *> ns = it.nodes;
180  for (int i = 0; i < ns.size(); i++)
181  {
182  cfiIdToTypes[ns[i]->number].insert(LibUtilities::eHexahedron);
183  }
184  }
185  vector<cfi::ElementDefinition> *tets =
186  m_model->getElements(cfi::SUBTYPE_TE4, 4);
187  for (auto &it : *tets)
188  {
189  vector<cfi::Node *> ns = it.nodes;
190  for (int i = 0; i < ns.size(); i++)
191  {
192  cfiIdToTypes[ns[i]->number].insert(LibUtilities::eTetrahedron);
193  }
194  }
195 
196  WARNINGL0(nodes.size() == cfiIdToTypes.size(), "not all nodes marked");
197 
198  int id = 0;
199 
200  for (int i = 1; i <= 3; i++)
201  {
202  for (auto &it : cfiIdToTypes)
203  {
204  if (it.second.size() == i)
205  {
206  nodes[it.first]->m_id = id++;
207  }
208  }
209  }
210 
211  WARNINGL0(id == nodes.size(), "not all nodes numbered");
212 
213  int prefix = m_mesh->m_cad->GetNumSurf() > 100 ? 1000 : 100;
214 
215  if (m_mesh->m_verbose)
216  {
217  cout << "prisms " << prisms->size() << endl;
218  }
219 
220  int nm[6] = {3, 2, 5, 0, 1, 4};
221  for (auto &it : *prisms)
222  {
223  vector<NodeSharedPtr> n(6);
224 
225  vector<cfi::Node *> ns = it.nodes;
226 
227  for (int j = 0; j < ns.size(); j++)
228  {
229  n[nm[j]] = nodes[ns[j]->number];
230  }
231 
232  vector<int> tags;
233  tags.push_back(prefix + 1);
234  ElmtConfig conf(LibUtilities::ePrism, 1, false, false);
235 
237  LibUtilities::ePrism, conf, n, tags);
238 
239  m_mesh->m_element[3].push_back(E);
240  }
241 
242  if (m_mesh->m_verbose)
243  {
244  cout << "tets " << tets->size() << endl;
245  }
246 
247  for (auto &it : *tets)
248  {
249  vector<NodeSharedPtr> n;
250  vector<cfi::Node *> ns = it.nodes;
251 
252  for (int j = 0; j < ns.size(); j++)
253  {
254  n.push_back(nodes[ns[j]->number]);
255  }
256 
257  vector<int> tags;
258  tags.push_back(prefix);
259  ElmtConfig conf(LibUtilities::eTetrahedron, 1, false, false);
261  LibUtilities::eTetrahedron, conf, n, tags);
262 
263  m_mesh->m_element[3].push_back(E);
264  }
265 
266  if (m_mesh->m_verbose)
267  {
268  cout << "hexes " << hexs->size() << endl;
269  }
270 
271  for (auto &it : *hexs)
272  {
273  vector<NodeSharedPtr> n;
274  vector<cfi::Node *> ns = it.nodes;
275 
276  for (int j = 0; j < ns.size(); j++)
277  {
278  n.push_back(nodes[ns[j]->number]);
279  }
280 
281  vector<int> tags;
282  tags.push_back(prefix + 2);
283  ElmtConfig conf(LibUtilities::eHexahedron, 1, false, false);
285  LibUtilities::eHexahedron, conf, n, tags);
286 
287  m_mesh->m_element[3].push_back(E);
288  }
289 
290  ProcessVertices();
291  ProcessEdges();
292  ProcessFaces();
293  ProcessElements();
295 
296  vector<cfi::ElementDefinition> *tris =
297  m_model->getElements(cfi::SUBTYPE_TR3, 3);
298  if (m_mesh->m_verbose)
299  {
300  cout << "tris " << tris->size() << endl;
301  }
302 
303  for (auto &it : *tris)
304  {
305  cfi::MeshableEntity *p = it.parent;
306  auto f = m_nameToFaceId.find(p->getName());
307 
308  if (f != m_nameToFaceId.end())
309  {
310  vector<NodeSharedPtr> n;
311  vector<cfi::Node *> ns = it.nodes;
312 
313  for (int j = 0; j < ns.size(); j++)
314  {
315  n.push_back(nodes[ns[j]->number]);
316  }
317 
318  vector<int> tags;
319  tags.push_back(f->second);
320  ElmtConfig conf(LibUtilities::eTriangle, 1, false, false, false);
322  LibUtilities::eTriangle, conf, n, tags);
323 
325  new Face(E->GetVertexList(), vector<NodeSharedPtr>(),
326  E->GetEdgeList(), LibUtilities::ePolyEvenlySpaced));
327 
328  FaceSet::iterator fnd = m_mesh->m_faceSet.find(fc);
329  ASSERTL0(fnd != m_mesh->m_faceSet.end(),
330  "surface element not found in mesh");
331 
332  FaceSharedPtr mf = *fnd;
333 
334  if (mf->m_elLink.size() == 1)
335  {
336  E->m_parentCAD = m_mesh->m_cad->GetSurf(f->second);
337  m_mesh->m_element[2].push_back(E);
338  }
339  }
340  }
341 
342  vector<cfi::ElementDefinition> *quads =
343  m_model->getElements(cfi::SUBTYPE_QU4, 4);
344  if (m_mesh->m_verbose)
345  {
346  cout << "quads " << quads->size() << endl;
347  }
348 
349  for (auto &it : *quads)
350  {
351  cfi::MeshableEntity *p = it.parent;
352  auto f = m_nameToFaceId.find(p->getName());
353 
354  if (f != m_nameToFaceId.end())
355  {
356  vector<NodeSharedPtr> n;
357  vector<cfi::Node *> ns = it.nodes;
358 
359  for (int j = 0; j < ns.size(); j++)
360  {
361  n.push_back(nodes[ns[j]->number]);
362  }
363 
364  vector<int> tags;
365  tags.push_back(f->second);
366  ElmtConfig conf(LibUtilities::eQuadrilateral, 1, false, false,
367  false);
369  LibUtilities::eQuadrilateral, conf, n, tags);
370 
372  new Face(E->GetVertexList(), vector<NodeSharedPtr>(),
373  E->GetEdgeList(), LibUtilities::ePolyEvenlySpaced));
374 
375  FaceSet::iterator fnd = m_mesh->m_faceSet.find(fc);
376  ASSERTL0(fnd != m_mesh->m_faceSet.end(),
377  "surface element not found in mesh");
378 
379  FaceSharedPtr mf = *fnd;
380 
381  if (mf->m_elLink.size() == 1)
382  {
383  E->m_parentCAD = m_mesh->m_cad->GetSurf(f->second);
384  m_mesh->m_element[2].push_back(E);
385  }
386  }
387  }
388 
389  ProcessVertices();
390  ProcessEdges();
391  ProcessFaces();
392  ProcessElements();
394 
395  // surface edges are different to mesh edges
396  // first of all need to process them so they are unique
397  // and then find CAD for them from beams
398 
399  EdgeSet surfaceEdges;
400  for (int i = 0; i < m_mesh->m_element[2].size(); i++)
401  {
402  vector<EdgeSharedPtr> es = m_mesh->m_element[2][i]->GetEdgeList();
403  for (int j = 0; j < es.size(); j++)
404  {
405  surfaceEdges.insert(es[j]);
406  }
407  }
408 
409  vector<cfi::ElementDefinition> *beams =
410  m_model->getElements(cfi::SUBTYPE_BE2, 2);
411  if (m_mesh->m_verbose)
412  {
413  cout << "beams " << beams->size() << endl;
414  }
415 
416  for (auto &it : *beams)
417  {
418  cfi::MeshableEntity *p = it.parent;
419  auto f = m_nameToCurveId.find(p->getName());
420 
421  if (f != m_nameToCurveId.end())
422  {
423  vector<NodeSharedPtr> n;
424  vector<cfi::Node *> ns = it.nodes;
425 
426  for (int j = 0; j < ns.size(); j++)
427  {
428  n.push_back(nodes[ns[j]->number]);
429  }
430 
431  // going to create a edge from the cfi element and find its
432  // counterpart
433  // in the m_mesh edgeset
434 
435  EdgeSharedPtr ec = EdgeSharedPtr(new Edge(n[0], n[1]));
436 
437  EdgeSet::iterator find = surfaceEdges.find(ec);
438  if (find == surfaceEdges.end())
439  {
440  continue;
441  }
442 
443  EdgeSharedPtr me = *find;
444 
445  me->m_parentCAD = m_mesh->m_cad->GetCurve(f->second);
446  }
447  }
448 }
449 }
450 }
std::map< std::string, int > m_nameToFaceId
Definition: CFIMesh.h:70
std::shared_ptr< CADSurf > CADSurfSharedPtr
Definition: CADCurve.h:51
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
Basic information about an element.
Definition: ElementConfig.h:49
Represents an edge which joins two points.
Definition: Edge.h:58
std::unordered_set< EdgeSharedPtr, EdgeHash > EdgeSet
Definition: Edge.h:159
std::shared_ptr< CADVert > CADVertSharedPtr
Definition: CADCurve.h:49
Represents a face comprised of three or more edges.
Definition: Face.h:63
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
std::shared_ptr< Node > NodeSharedPtr
Definition: CADVert.h:49
std::shared_ptr< Face > FaceSharedPtr
Definition: Face.h:155
1D Evenly-spaced points using Lagrange polynomial
Definition: PointsType.h:64
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
std::pair< ModuleType, std::string > ModuleKey
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.
std::shared_ptr< CADCurve > CADCurveSharedPtr
Definition: CADCurve.h:219
#define WARNINGL0(condition, msg)
Definition: ErrorUtil.hpp:223
double NekDouble
Abstract base class for processing modules.
virtual NEKMESHUTILS_EXPORT void ProcessVertices()
Extract element vertices.
std::map< std::string, int > m_nameToVertId
Definition: CFIMesh.h:71
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
CADSystemCFISharedPtr m_cad
Definition: CFIMesh.h:67
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:199
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.
std::map< std::string, int > m_nameToCurveId
Definition: CFIMesh.h:69
ModuleFactory & GetModuleFactory()