44 #include <boost/algorithm/string.hpp>    49 namespace NekMeshUtils
    54     "Generates a 2D mesh");
    59         ConfigOption(
false, 
"", 
"Generate parallelograms on these curves");
    61         ConfigOption(
false, 
"0.0", 
"Parallelogram layer thickness");
    63         ConfigOption(
false, 
"", 
"Set of pairs of periodic curves");
    65         ConfigOption(
false, 
"2.0", 
"Boundary layer thickness adjustment");
    69         ConfigOption(
true, 
"0", 
"Smooth the BL normal directions to avoid "    70                                 "(nearly) intersecting normals");
    72         false, 
"0.5", 
"Threshold to space out BL according to Delta");
    74         ConfigOption(
false, 
"", 
"Surfaces where spacing out shouldn't be used");
    85     ASSERTL0(fabs(bndBox[5] - bndBox[4]) < 1.0e-7, 
"CAD isn't 2D");
    89         cout << endl << 
"2D meshing" << endl;
    90         cout << endl << 
"\tCurve meshing:" << endl << endl;
   105     for (
int i = 1; i <= 
m_mesh->m_cad->GetNumCurve(); i++)
   112         vector<unsigned int>::iterator f =
   124                 vector<CADVertSharedPtr> vertices =
   125                     m_mesh->m_cad->GetCurve(i)->GetVertex();
   132                     loc = vertices[0]->GetLoc();
   140                     loc = vertices[1]->GetLoc();
   170         for (
int i = 1; i <= 
m_mesh->m_cad->GetNumSurf(); i++)
   179             vector<NodeSharedPtr> nodes =
   182             if (ic.second == 0 || ic.second == 2)
   184                 nodes.erase(nodes.begin());
   186             if (ic.second == 1 || ic.second == 2)
   188                 nodes.erase(nodes.end() - 1);
   201         cout << endl << 
"\tFace meshing:" << endl << endl;
   204     for (
int i = 1; i <= 
m_mesh->m_cad->GetNumSurf(); i++)
   214         m_facemeshes[i]->Mesh();
   219     EdgeSet::iterator it;
   220     for (
auto &it : 
m_mesh->m_edgeSet)
   222         vector<NodeSharedPtr> ns;
   223         ns.push_back(it->m_n1);
   224         ns.push_back(it->m_n2);
   230         tags.push_back(it->m_parentCAD->GetId());
   233         m_mesh->m_element[1].push_back(E2);
   251     set<CADVertSharedPtr> cadverts;
   255         vector<CADVertSharedPtr> vertices =
   256             m_mesh->m_cad->GetCurve(it)->GetVertex();
   258         for (
auto &iv : vertices)
   260             set<CADVertSharedPtr>::iterator is = cadverts.find(iv);
   262             if (is != cadverts.end())
   276     for (
int i = 1; i <= 
m_mesh->m_cad->GetNumCurve(); ++i)
   278         if (
find(m_blCurves.begin(), m_blCurves.end(), i) != m_blCurves.end())
   283         vector<CADVertSharedPtr> vertices =
   284             m_mesh->m_cad->GetCurve(i)->GetVertex();
   286         for (
int j = 0; j < 2; ++j)
   288             if (!cadverts.count(vertices[j]))
   309         cout << endl << 
"\tBoundary layer meshing:" << endl << endl;
   316         vector<EdgeSharedPtr> localedges = 
m_curvemeshes[it]->GetMeshEdges();
   317         for (
auto &ie : localedges)
   328     map<int, Array<OneD, NekDouble>> edgeNormals;
   333             m_mesh->m_cad->GetCurve(it)->GetOrienationWRT(faceid);
   334         vector<EdgeSharedPtr> es = 
m_curvemeshes[it]->GetMeshEdges();
   343             p1 = ie->m_n1->GetCADSurfInfo(faceid);
   344             p2 = ie->m_n2->GetCADSurfInfo(faceid);
   346             n[0] = p1[1] - p2[1];
   347             n[1] = p2[0] - p1[0];
   353             NekDouble mag = sqrt(n[0] * n[0] + n[1] * n[1]);
   357             np[0] = p1[0] + n[0];
   358             np[1] = p1[1] + n[1];
   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]);
   366             edgeNormals[ie->m_id] = n;
   370     bool adjust           = 
m_config[
"bltadjust"].beenSet;
   372     bool adjustEverywhere = 
m_config[
"adjustblteverywhere"].beenSet;
   373     bool smoothbl         = 
m_config[
"smoothbl"].beenSet;
   374     bool spaceoutbl       = 
m_config[
"spaceoutbl"].beenSet;
   379         WARNINGL0(
false, 
"BndLayerAdjustment too low, corrected to 2.0");
   383     map<NodeSharedPtr, NodeSharedPtr> nodeNormals;
   386         ASSERTL0(it.second.size() == 1 || it.second.size() == 2,
   387                  "weirdness, most likely bl_surfs are incorrect");
   391         if (it.second.size() == 1)
   393             vector<CADCurveSharedPtr> curves = it.first->GetCADCurves();
   395             vector<EdgeSharedPtr> edges =
   397             vector<EdgeSharedPtr>::iterator ie =
   398                 find(edges.begin(), edges.end(), it.second[0]);
   400                 (ie == edges.end()) ? curves[0]->GetId() : curves[1]->GetId();
   402             vector<NodeSharedPtr> nodes =
   404             nodeNormals[it.first] =
   405                 (nodes[0] == it.first) ? nodes[1] : nodes[nodes.size() - 2];
   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]);
   419                                            it.first->m_y, 0.0, 0.0);
   423             if (adjustEverywhere || it.first->GetNumCadCurve() > 1)
   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);
   431         n[0]             = n[0] * t + it.first->m_x;
   432         n[1]             = n[1] * t + it.first->m_y;
   434             new Node(
m_mesh->m_numNodes++, n[0], n[1], 0.0));
   437         nn->SetCADSurf(s, uv);
   438         nodeNormals[it.first] = nn;
   446         map<NodeSharedPtr, vector<NodeSharedPtr>> unitNormals;
   448         map<NodeSharedPtr, NekDouble> dist;
   464                 Node r = *nodeNormals[
p] - *
p;
   465                 Node s = *nodeNormals[q] - *q;
   482                 if ((-0.5 < t && t <= 1.5) || (-0.5 < u && u <= 1.5))
   484                     dist[
p] = sqrt(r.
abs2());
   485                     dist[q] = sqrt(s.
abs2());
   488                         make_shared<Node>(r / dist[
p] + s / dist[q]);
   490                     unitNormals[
p].push_back(sum);
   491                     unitNormals[q].push_back(sum);
   496             for (
const auto &it : unitNormals)
   498                 Node avg(0, 0.0, 0.0, 0.0);
   500                 for (
const auto &i : it.second)
   505                 avg /= sqrt(avg.
abs2());
   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));
   513                     *nodeNormals[it.first]->GetCADSurfs().begin();
   515                 nn->SetCADSurf(s, uv);
   517                 nodeNormals[it.first] = nn;
   519         } 
while (unitNormals.size() && count++ < 50);
   525                 cout << 
"\t\tNormals smoothed in " << count << 
" iterations."   530                 cout << 
"\t\tNormals smoothed. Algorithm didn't converge after "   531                      << count << 
" iterations." << endl;
   539         if (spaceoutthr < 0.0 || spaceoutthr > 1.0)
   541             WARNINGL0(
false, 
"The boundary layer space out threshold should be "   542                              "between 0 and 1. It will now be adjusted to "   547         vector<unsigned int> nospaceoutsurf;
   552         vector<deque<NodeSharedPtr>> nodesToMove;
   565                 auto it = 
find(nospaceoutsurf.begin(), nospaceoutsurf.end(),
   566                                ie->m_parentCAD->GetId());
   567                 if (it != nospaceoutsurf.end())
   576                     m_mesh->m_octree->Query(((*n1 + *n2) / 2.0).GetLoc());
   577                 NekDouble realD = sqrt((*n1 - *n2).abs2());
   580                 if (realD < spaceoutthr * targetD)
   582                     bool connected = 
false;
   584                     for (
auto &il : nodesToMove)
   586                         if (il.front() == n1)
   592                         if (il.front() == n2)
   615                         deque<NodeSharedPtr> newList;
   616                         newList.push_back(n1);
   617                         newList.push_back(n2);
   619                         nodesToMove.push_back(newList);
   624             for (
int i = 0;; ++i)
   629                 for (
int i1 = 0; i1 < nodesToMove.size(); ++i1)
   634                     for (
int i2 = i1 + 1; i2 < nodesToMove.size(); ++i2)
   639                         if (n11 == n21 || n11 == n22 || n12 == n21 ||
   642                             if (n11 == n21 || n12 == n22)
   644                                 reverse(nodesToMove[i2].begin(),
   645                                         nodesToMove[i2].end());
   646                                 n21 = nodesToMove[i2].front();
   647                                 n22 = nodesToMove[i2].back();
   652                                 nodesToMove[i1].insert(nodesToMove[i1].begin(),
   653                                                        nodesToMove[i2].begin(),
   654                                                        nodesToMove[i2].end() -
   659                                 nodesToMove[i1].insert(nodesToMove[i1].end(),
   660                                                        nodesToMove[i2].begin() +
   662                                                        nodesToMove[i2].end());
   665                             nodesToMove.erase(nodesToMove.begin() + i2);
   676                 set<EdgeSharedPtr> addedEdges;
   680                 for (
auto &il : nodesToMove)
   688                     for (
const auto &ie : m_blEdges)
   691                             find(nospaceoutsurf.begin(), nospaceoutsurf.end(),
   692                                  ie->m_parentCAD->GetId());
   693                         if (addedEdges.count(ie) || it != nospaceoutsurf.end())
   705                             if (n11 == n21 && n12 != n22)
   709                             else if (n11 == n22 && n12 != n21)
   716                                 il.push_front(frontPush);
   718                                 addedEdges.insert(ie);
   721                         if (n14 && !frontPush)
   723                             if (n14 == n21 && n13 != n22)
   727                             if (n14 == n22 && n13 != n21)
   734                                 il.push_back(backPush);
   736                                 addedEdges.insert(ie);
   751             for (
const auto &il : nodesToMove)
   756                 vector<NekDouble> deltas;
   759                 for (
int i = 0; i < il.size() - 1; ++i)
   765                         m_mesh->m_octree->Query(((*n1 + *n2) / 2.0).GetLoc()));
   766                     total += deltas.back();
   769                 for (
auto &
id : deltas)
   776                 for (
int i = 1; i < il.size() - 1; ++i)
   778                     runningTotal += deltas[i - 1];
   780                         (*ni * (1.0 - runningTotal) + *nf * runningTotal)
   784                         m_mesh->m_cad->GetSurf(faceid)->locuv(loc);
   786                     il[i]->Move(loc, faceid, uv);
   789         } 
while (nodesToMove.size() && count++ < 50);
   795                 cout << 
"\t\tBL spaced out in " << count << 
" iterations."   800                 cout << 
"\t\tBL spaced out. Algorithm didn't converge after "   801                      << count << 
" iterations." << endl;
   806     for (
auto &it : m_blCurves)
   809             m_mesh->m_cad->GetCurve(it)->GetOrienationWRT(faceid);
   810         vector<NodeSharedPtr> ns = 
m_curvemeshes[it]->GetMeshPoints();
   811         vector<NodeSharedPtr> newNs;
   814             newNs.push_back(nodeNormals[in]);
   820             reverse(ns.begin(), ns.end());
   822         for (
int i = 0; i < ns.size() - 1; ++i)
   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]]);
   834             E->m_parentCAD = 
m_mesh->m_cad->GetSurf(faceid);
   835             for (
int j = 0; j < E->GetEdgeCount(); ++j)
   837                 pair<EdgeSet::iterator, bool> testIns;
   840                 EdgeSet::iterator s = 
m_mesh->m_edgeSet.find(ed);
   841                 if (!(s == 
m_mesh->m_edgeSet.end()))
   847             m_mesh->m_element[2].push_back(E);
   855     set<unsigned> periodic;
   858     string s = 
m_config[
"periodic"].as<
string>();
   859     vector<string> lines;
   861     boost::split(lines, s, boost::is_any_of(
":"));
   863     for (
auto &il : lines)
   866         boost::split(tmp, il, boost::is_any_of(
","));
   868         ASSERTL0(tmp.size() == 2, 
"periodic pairs ill-defined");
   870         vector<unsigned> data(2);
   871         data[0] = boost::lexical_cast<
unsigned>(tmp[0]);
   872         data[1] = boost::lexical_cast<
unsigned>(tmp[1]);
   874         ASSERTL0(!periodic.count(data[0]), 
"curve already periodic");
   875         ASSERTL0(!periodic.count(data[1]), 
"curve already periodic");
   878         periodic.insert(data[0]);
   879         periodic.insert(data[1]);
   894         cout << 
"\t\tPeriodic boundary conditions" << endl;
   895         for (
auto &it : m_periodicPairs)
   897             cout << 
"\t\t\tCurves " << it.first << 
" => " << it.second << endl;
   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;
 
std::shared_ptr< CADSurf > CADSurfSharedPtr
#define ASSERTL0(condition, msg)
Basic information about an element. 
int PrintProgressbar(const int position, const int goal, const std::string message, int lastprogress=-1)
Prints a progressbar. 
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation. 
NEKMESHUTILS_EXPORT NekDouble abs2() const
std::vector< unsigned int > m_blCurves
list of curves needing a BL 
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 
NekDouble m_y
Y-coordinate. 
MeshSharedPtr m_mesh
Mesh object. 
std::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge. 
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh. 
ElementFactory & GetElementFactory()
std::map< unsigned, unsigned > m_blends
map of curves and Bl ends: 0, 1 or 2 (for both) 
Represents a point in the domain. 
std::shared_ptr< Node > NodeSharedPtr
int m_thickness_ID
BL thickness expression ID. 
std::map< unsigned, unsigned > m_periodicPairs
map of periodic curve pairs 
LibUtilities::Interpreter m_thickness
BL thickness expression. 
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey. 
std::pair< ModuleType, std::string > ModuleKey
virtual NEKMESHUTILS_EXPORT void ProcessFaces(bool ReprocessFaces=true)
Extract element faces. 
std::shared_ptr< Element > ElementSharedPtr
virtual NEKMESHUTILS_EXPORT void ProcessElements()
Generate element IDs. 
Represents a command-line configuration option. 
#define WARNINGL0(condition, msg)
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 
std::map< std::string, ConfigOption > m_config
List of configuration values. 
NEKMESHUTILS_EXPORT Node curl(const Node &pSrc) const
NekDouble m_x
X-coordinate. 
Abstract base class for processing modules. 
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)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory. 
std::map< NodeSharedPtr, std::vector< EdgeSharedPtr > > m_nodesToEdge
map of BL curve nodes to adjacent edges 
NekDouble m_z
Z-coordinate. 
std::pair< ModuleType, std::string > ModuleKey
std::map< int, CurveMeshSharedPtr > m_curvemeshes
map of individual curve meshes of the curves in the domain 
virtual NEKMESHUTILS_EXPORT void ProcessComposites()
Generate composites. 
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. ...