Nektar++
InputMCF.cpp
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // File: InputCAD.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: create mesh from cad using mesh utils
32 //
33 ////////////////////////////////////////////////////////////////////////////////
34 
37 
38 #include <boost/thread.hpp>
39 #include <boost/algorithm/string.hpp>
40 
41 #include <tinyxml.h>
42 
43 #include "InputMCF.h"
44 
45 using namespace std;
46 using namespace Nektar::NekMeshUtils;
47 
48 namespace Nektar
49 {
50 namespace Utilities
51 {
52 
53 ModuleKey InputMCF::className = GetModuleFactory().RegisterCreatorFunction(
54  ModuleKey(eInputModule, "mcf"), InputMCF::create,
55  "Reads mesh configuration and will generate the mesh file.");
56 
57 /**
58  * @brief Set up InputCAD object.
59  */
60 InputMCF::InputMCF(MeshSharedPtr m) : InputModule(m)
61 {
62 }
63 
65 {
66 }
67 
68 void InputMCF::ParseFile(string nm)
69 {
70  vector<string> filename;
71  filename.push_back(nm);
72 
73  char *prgname = (char*)"NekMesh";
75  LibUtilities::SessionReader::CreateInstance(1, &prgname, filename);
76  pSession->InitSession();
77 
78  auto comm = pSession->GetComm();
79  if (comm->GetType().find("MPI") != std::string::npos)
80  {
81  m_mesh->m_comm = comm;
82  }
83 
84  ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING"), "no meshing tag");
85  ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING/INFORMATION"),
86  "no information tag");
87  ASSERTL0(pSession->DefinesElement("NEKTAR/MESHING/PARAMETERS"),
88  "no parameters tag");
89 
90  TiXmlElement *mcf = pSession->GetElement("NEKTAR/MESHING");
91 
92  // Save MESHING tag as provenance information.
93  std::stringstream ss;
94  ss << *mcf;
95  m_mesh->m_metadata["XML_NekMeshMCF"] = ss.str();
96 
97  TiXmlElement *info = mcf->FirstChildElement("INFORMATION");
98  TiXmlElement *I = info->FirstChildElement("I");
99  map<string, string> information;
100  while (I)
101  {
102  string tmp1, tmp2;
103  I->QueryStringAttribute("PROPERTY", &tmp1);
104  I->QueryStringAttribute("VALUE", &tmp2);
105  information[tmp1] = tmp2;
106  I = I->NextSiblingElement("I");
107  }
108 
109  TiXmlElement *param = mcf->FirstChildElement("PARAMETERS");
110  TiXmlElement *P = param->FirstChildElement("P");
111  map<string, string> parameters;
112  while (P)
113  {
114  string tmp1, tmp2;
115  P->QueryStringAttribute("PARAM", &tmp1);
116  P->QueryStringAttribute("VALUE", &tmp2);
117  parameters[tmp1] = tmp2;
118  P = P->NextSiblingElement("P");
119  }
120 
121  set<string> boolparameters;
122 
123  if (pSession->DefinesElement("NEKTAR/MESHING/BOOLPARAMETERS"))
124  {
125  TiXmlElement *bparam = mcf->FirstChildElement("BOOLPARAMETERS");
126  TiXmlElement *BP = bparam->FirstChildElement("P");
127 
128  while (BP)
129  {
130  string tmp;
131  BP->QueryStringAttribute("VALUE", &tmp);
132  boolparameters.insert(tmp);
133  BP = BP->NextSiblingElement("P");
134  }
135  }
136 
137  set<string> refinement;
138  if (pSession->DefinesElement("NEKTAR/MESHING/REFINEMENT"))
139  {
140  TiXmlElement *refine = mcf->FirstChildElement("REFINEMENT");
141  TiXmlElement *L = refine->FirstChildElement("LINE");
142 
143  while (L)
144  {
145  stringstream ss;
146  TiXmlElement *T = L->FirstChildElement("X1");
147  ss << T->GetText() << ",";
148  T = L->FirstChildElement("Y1");
149  ss << T->GetText() << ",";
150  T = L->FirstChildElement("Z1");
151  ss << T->GetText() << ",";
152  T = L->FirstChildElement("X2");
153  ss << T->GetText() << ",";
154  T = L->FirstChildElement("Y2");
155  ss << T->GetText() << ",";
156  T = L->FirstChildElement("Z2");
157  ss << T->GetText() << ",";
158  T = L->FirstChildElement("R");
159  ss << T->GetText() << ",";
160  T = L->FirstChildElement("D");
161  ss << T->GetText();
162 
163  refinement.insert(ss.str());
164 
165  L = L->NextSiblingElement("LINE");
166  }
167  }
168 
169  set<string> periodic;
170  if (pSession->DefinesElement("NEKTAR/MESHING/PERIODIC"))
171  {
172  TiXmlElement *per = mcf->FirstChildElement("PERIODIC");
173  TiXmlElement *pair = per->FirstChildElement("P");
174 
175  while (pair)
176  {
177  string tmp;
178  pair->QueryStringAttribute("PAIR", &tmp);
179  periodic.insert(tmp);
180  pair = pair->NextSiblingElement("P");
181  }
182  }
183 
184  auto it = information.find("CADFile");
185  ASSERTL0(it != information.end(), "no cadfile defined");
186  m_cadfile = it->second;
187 
188  it = information.find("MeshType");
189  ASSERTL0(it != information.end(), "no meshtype defined");
190 
191  m_cfiMesh = it->second == "CFI";
192  m_makeBL = it->second == "3DBndLayer";
193  m_2D = it->second == "2D";
194  m_manifold = it->second == "Manifold";
195 
196  if (it->second == "2DBndLayer")
197  {
198  m_makeBL = true;
199  m_2D = true;
200  }
201 
202  if (!m_makeBL && !m_2D && !m_manifold && !m_cfiMesh)
203  {
204  ASSERTL0(it->second == "3D", "unsure on MeshType")
205  }
206 
207  it = parameters.find("MinDelta");
208  ASSERTL0(it != parameters.end(), "no mindelta defined");
209  m_minDelta = it->second;
210 
211  it = parameters.find("MaxDelta");
212  ASSERTL0(it != parameters.end(), "no maxdelta defined");
213  m_maxDelta = it->second;
214 
215  it = parameters.find("EPS");
216  ASSERTL0(it != parameters.end(), "no eps defined");
217  m_eps = it->second;
218 
219  it = parameters.find("Order");
220  ASSERTL0(it != parameters.end(), "no order defined");
221  m_order = it->second;
222 
223  if (m_makeBL)
224  {
225  it = parameters.find("BndLayerSurfaces");
226  ASSERTL0(it != parameters.end(), "no BndLayersurfs defined");
227  m_blsurfs = it->second;
228 
229  it = parameters.find("BndLayerThickness");
230  ASSERTL0(it != parameters.end(), "no BndLayerthick defined");
231  m_blthick = it->second;
232 
233  it = parameters.find("BndLayerLayers");
234  m_splitBL = it != parameters.end();
235  if (m_splitBL)
236  {
237  m_bllayers = it->second;
238  it = parameters.find("BndLayerProgression");
239  m_blprog = it != parameters.end() ? it->second : "2.0";
240  }
241 
242  it = parameters.find("BndLayerAdjustment");
243  if (it != parameters.end())
244  {
245  m_adjust = true;
246  m_adjustment = it->second;
247  }
248  else
249  {
250  m_adjust = false;
251  }
252 
253  it = parameters.find("SpaceOutBndLayer");
254  if (it != parameters.end())
255  {
256  m_spaceoutbl = true;
257  m_spaceoutblthr = it->second;
258 
259  it = parameters.find("NoSpaceOutSurf");
260  if (it != parameters.end())
261  {
262  m_nospaceoutsurf = it->second;
263  }
264  }
265  else
266  {
267  m_spaceoutbl = false;
268  }
269  }
270  else
271  {
272  m_splitBL = false;
273  }
274 
275  m_naca = false;
276  if (m_2D && m_cadfile.find('.') == std::string::npos)
277  {
278  m_naca = true;
279 
280  stringstream ss;
281  it = parameters.find("Xmin");
282  ASSERTL0(it != parameters.end(), "no xmin defined");
283  ss << it->second << ",";
284  it = parameters.find("Ymin");
285  ASSERTL0(it != parameters.end(), "no ymin defined");
286  ss << it->second << ",";
287  it = parameters.find("Xmax");
288  ASSERTL0(it != parameters.end(), "no xmax defined");
289  ss << it->second << ",";
290  it = parameters.find("Ymax");
291  ASSERTL0(it != parameters.end(), "no zmax defined");
292  ss << it->second << ",";
293  it = parameters.find("AOA");
294  ASSERTL0(it != parameters.end(), "no aoa defined");
295  ss << it->second;
296 
297  m_nacadomain = ss.str();
298  }
299 
300  auto sit = boolparameters.find("SurfaceOptimiser");
301  m_surfopti = sit != boolparameters.end();
302  sit = boolparameters.find("WriteOctree");
303  m_woct = sit != boolparameters.end();
304  sit = boolparameters.find("VariationalOptimiser");
305  m_varopti = sit != boolparameters.end();
306  sit = boolparameters.find("BndLayerAdjustEverywhere");
307  m_adjustall = sit != boolparameters.end();
308  sit = boolparameters.find("SmoothBndLayer");
309  m_smoothbl = sit != boolparameters.end();
310 
311  m_refine = refinement.size() > 0;
312  if (m_refine)
313  {
314  stringstream ss;
315  for (sit = refinement.begin(); sit != refinement.end(); sit++)
316  {
317  ss << *sit;
318  ss << ":";
319  }
320  m_refinement = ss.str();
321  m_refinement.erase(m_refinement.end() - 1);
322  }
323 
324  if (periodic.size() > 0)
325  {
326  stringstream ss;
327  for (sit = periodic.begin(); sit != periodic.end(); ++sit)
328  {
329  ss << *sit;
330  ss << ":";
331  }
332  m_periodic = ss.str();
333  m_periodic.erase(m_periodic.end() - 1);
334  }
335 }
336 
338 {
339  ParseFile(m_config["infile"].as<string>());
340 
341  m_mesh->m_expDim = 3;
342  m_mesh->m_spaceDim = 3;
343  m_mesh->m_nummode = boost::lexical_cast<int>(m_order) + 1;
344 
345  ModuleSharedPtr module;
346 
347  ////**** CAD ****////
348  module = GetModuleFactory().CreateInstance(
349  ModuleKey(eProcessModule, "loadcad"), m_mesh);
350  module->RegisterConfig("filename", m_cadfile);
351  if (m_mesh->m_verbose)
352  {
353  module->RegisterConfig("verbose", "");
354  }
355  if (m_2D)
356  {
357  module->RegisterConfig("2D", "");
358  }
359  if (m_naca)
360  {
361  module->RegisterConfig("NACA", m_nacadomain);
362  }
363 
364  if (m_cfiMesh)
365  {
366  module->RegisterConfig("CFIMesh", "");
367  }
368 
369  module->SetDefaults();
370  module->Process();
371 
372  if (!m_cfiMesh)
373  {
374  ////**** OCTREE ****////
375  module = GetModuleFactory().CreateInstance(
376  ModuleKey(eProcessModule, "loadoctree"), m_mesh);
377  module->RegisterConfig("mindel", m_minDelta);
378  module->RegisterConfig("maxdel", m_maxDelta);
379  module->RegisterConfig("eps", m_eps);
380  if (m_refine)
381  {
382  module->RegisterConfig("refinement", m_refinement);
383  }
384  if (m_woct)
385  {
386  module->RegisterConfig("writeoctree", "");
387  }
388 
389  module->SetDefaults();
390  module->Process();
391  }
392 
393  ////**** LINEAR MESHING ****////
394  if (m_2D)
395  {
396  ////**** 2DGenerator ****////
397  m_mesh->m_expDim = 2;
398  m_mesh->m_spaceDim = 2;
399  module = GetModuleFactory().CreateInstance(
400  ModuleKey(eProcessModule, "2dgenerator"), m_mesh);
401  if (m_makeBL)
402  {
403  module->RegisterConfig("blcurves", m_blsurfs);
404  module->RegisterConfig("blthick", m_blthick);
405 
406  if (m_adjust)
407  {
408  module->RegisterConfig("bltadjust", m_adjustment);
409 
410  if (m_adjustall)
411  {
412  module->RegisterConfig("adjustblteverywhere", "");
413  }
414  }
415 
416  if (m_smoothbl)
417  {
418  module->RegisterConfig("smoothbl", "");
419  }
420 
421  if (m_spaceoutbl)
422  {
423  module->RegisterConfig("spaceoutbl", m_spaceoutblthr);
424  module->RegisterConfig("nospaceoutsurf", m_nospaceoutsurf);
425  }
426  }
427  if (m_periodic.size())
428  {
429  module->RegisterConfig("periodic", m_periodic);
430  }
431 
432  try
433  {
434  module->SetDefaults();
435  module->Process();
436  }
437  catch (runtime_error &e)
438  {
439  cout << "2D linear mesh generator failed with message:" << endl;
440  cout << e.what() << endl;
441  cout << "No mesh file has been created" << endl;
442  abort();
443  }
444  }
445  else
446  {
447  ////**** Possible Mesh Sources ****////
448  if (m_cfiMesh)
449  {
450  ////**** CFI mesh ****////
451  module = GetModuleFactory().CreateInstance(
452  ModuleKey(eProcessModule, "cfimesh"), m_mesh);
453 
454  module->SetDefaults();
455  module->Process();
456  }
457  else
458  {
459  ////**** SurfaceMesh ****////
460  module = GetModuleFactory().CreateInstance(
461  ModuleKey(eProcessModule, "surfacemesh"), m_mesh);
462 
463  try
464  {
465  module->SetDefaults();
466  module->Process();
467  }
468  catch (runtime_error &e)
469  {
470  cout << "Surface meshing has failed with message:" << endl;
471  cout << e.what() << endl;
472  cout << "Any surfaces which were succsessfully meshed will be "
473  "dumped as a manifold mesh"
474  << endl;
475  m_mesh->m_expDim = 2;
476  ProcessVertices();
477  ProcessEdges();
478  ProcessFaces();
479  ProcessElements();
481  return;
482  }
483 
484  if (m_manifold)
485  {
486  // dont want to volume mesh
487  m_mesh->m_expDim = 2;
488  }
489  else
490  {
491  ////**** VolumeMesh ****////
492  module = GetModuleFactory().CreateInstance(
493  ModuleKey(eProcessModule, "volumemesh"), m_mesh);
494  if (m_makeBL)
495  {
496  module->RegisterConfig("blsurfs", m_blsurfs);
497  module->RegisterConfig("blthick", m_blthick);
498  module->RegisterConfig("bllayers", m_bllayers);
499  module->RegisterConfig("blprog", m_blprog);
500  }
501 
502  try
503  {
504  module->SetDefaults();
505  module->Process();
506  }
507  catch (runtime_error &e)
508  {
509  cout << "Volume meshing has failed with message:" << endl;
510  cout << e.what() << endl;
511  cout << "The linear surface mesh be dumped as a manifold "
512  "mesh"
513  << endl;
514  m_mesh->m_expDim = 2;
515  m_mesh->m_element[3].clear();
516  ProcessVertices();
517  ProcessEdges();
518  ProcessFaces();
519  ProcessElements();
521  return;
522  }
523  }
524  }
525  }
526 
527  ////**** HOSurface ****////
528  module = GetModuleFactory().CreateInstance(
529  ModuleKey(eProcessModule, "hosurface"), m_mesh);
530  if (m_surfopti)
531  {
532  module->RegisterConfig("opti", "");
533  }
534 
535  try
536  {
537  module->SetDefaults();
538  module->Process();
539  }
540  catch (runtime_error &e)
541  {
542  cout << "High-order surface meshing has failed with message:" << endl;
543  cout << e.what() << endl;
544  cout << "The mesh will be written as normal but the incomplete surface "
545  "will remain faceted"
546  << endl;
547  return;
548  }
549 
550  ////*** VARIATIONAL OPTIMISATION ****////
551  if (m_varopti)
552  {
553  unsigned int np = boost::thread::physical_concurrency();
554  if (m_mesh->m_verbose)
555  {
556  cout << "Detecting 4 cores, will attempt to run in parrallel"
557  << endl;
558  }
559  module = GetModuleFactory().CreateInstance(
560  ModuleKey(eProcessModule, "varopti"), m_mesh);
561  module->RegisterConfig("hyperelastic", "");
562  module->RegisterConfig("maxiter", "10");
563  module->RegisterConfig("numthreads", boost::lexical_cast<string>(np));
564 
565  try
566  {
567  module->SetDefaults();
568  module->Process();
569  }
570  catch (runtime_error &e)
571  {
572  cout << "Variational optimisation has failed with message:" << endl;
573  cout << e.what() << endl;
574  cout << "The mesh will be written as is, it may be invalid" << endl;
575  return;
576  }
577  }
578 
579  ////**** SPLIT BL ****////
580  if (m_splitBL)
581  {
582  module = GetModuleFactory().CreateInstance(
584  module->RegisterConfig("layers", m_bllayers);
585  module->RegisterConfig("surf", m_blsurfs);
586  module->RegisterConfig("nq",
587  boost::lexical_cast<string>(m_mesh->m_nummode));
588  module->RegisterConfig("r", m_blprog);
589 
590  try
591  {
592  module->SetDefaults();
593  module->Process();
594  }
595  catch (runtime_error &e)
596  {
597  cout << "Boundary layer splitting has failed with message:" << endl;
598  cout << e.what() << endl;
599  cout << "The mesh will be written as is, it may be invalid" << endl;
600  return;
601  }
602  }
603 
604  // apply surface labels
605  for (auto &it : m_mesh->m_composite)
606  {
607  ElementSharedPtr el = it.second->m_items[0];
608  if (el->m_parentCAD)
609  {
610  string name = el->m_parentCAD->GetName();
611  if (name.size() > 0)
612  {
613  m_mesh->m_faceLabels.insert(
614  make_pair(el->GetTagList()[0], name));
615  }
616  }
617  }
619 
620  ////**** Peralign ****////
621  if (m_2D && m_periodic.size())
622  {
623  vector<string> lines;
624  boost::split(lines, m_periodic, boost::is_any_of(":"));
625 
626  for (auto &il : lines)
627  {
628  module = GetModuleFactory().CreateInstance(
629  ModuleKey(eProcessModule, "peralign"), m_mesh);
630 
631  vector<string> tmp(2);
632  boost::split(tmp, il, boost::is_any_of(","));
633  module->RegisterConfig("surf1", tmp[0]);
634  module->RegisterConfig("surf2", tmp[1]);
635 
636  module->SetDefaults();
637  module->Process();
638  }
639  }
640 }
641 }
642 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::string m_spaceoutblthr
Definition: InputMCF.h:63
std::shared_ptr< Module > ModuleSharedPtr
STL namespace.
std::string m_adjustment
Definition: InputMCF.h:63
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Definition: Mesh.h:156
static SessionReaderSharedPtr CreateInstance(int argc, char *argv[])
Creates an instance of the SessionReader class.
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::string m_nacadomain
Definition: InputMCF.h:63
std::shared_ptr< Element > ElementSharedPtr
Definition: Edge.h:49
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs.
void ParseFile(std::string nm)
Definition: InputMCF.cpp:68
std::map< std::string, ConfigOption > m_config
List of configuration values.
NekDouble L
Abstract base class for input modules.
virtual NEKMESHUTILS_EXPORT void ProcessVertices()
Extract element vertices.
virtual NEKMESHUTILS_EXPORT void ProcessEdges(bool ReprocessEdges=true)
Extract element edges.
std::string m_refinement
Definition: InputMCF.h:63
std::string m_nospaceoutsurf
Definition: InputMCF.h:63
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
std::shared_ptr< SessionReader > SessionReaderSharedPtr
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites.
ModuleFactory & GetModuleFactory()