46 #include <boost/algorithm/string.hpp>    71         ConfigOption(
false, 
"-1", 
"Tag identifying first surface.");
    73         ConfigOption(
false, 
"-1", 
"Tag identifying first surface.");
    75         false, 
"", 
"Direction in which to align (either x, y, or z; "    76         "or vector with components separated by a comma). "    77         "If rot is specified this is interpreted as the axis or rotation");
    79         false, 
"", 
"Rotation to align composites in radians, i.e. PI/20");
    81         ConfigOption(
true, 
"0", 
"Attempt to reorient tets and prisms");
    83         ConfigOption(
false, 
"1e-8", 
"Tolerance to which to check planes are the same after rotation/translation");
    95     int surf1   = 
m_config[
"surf1"].as<
int>();
    96     int surf2   = 
m_config[
"surf2"].as<
int>();
    97     string dir  = 
m_config[
"dir"].as<
string>();
    98     string rot  = 
m_config[
"rot"].as<
string>();
    99     bool orient = 
m_config[
"orient"].as<
bool>();
   100     string tolerance = 
m_config[
"tol"].as<
string>();
   104         cerr << 
"WARNING: surf1 must be set to a positive integer. "   105              << 
"Skipping periodic alignment." << endl;
   111         cerr << 
"WARNING: surf2 must be set to a positive integer. "   112              << 
"Skipping periodic alignment." << endl;
   117     boost::split(tmp1, dir, boost::is_any_of(
","));
   120     boost::split(tmp2, rot, boost::is_any_of(
","));
   121     bool rotalign = 
false;
   133         rotangle = strEval.
Evaluate(ExprId);
   139         ASSERTL0(tmp1.size() == 1,
"rot must also be accompanied "   140                  "with a dir=\"x\",dir=\"y\" or dir=\"z\" option "   141                  "to specify axes of rotation");
   143     else if (tmp1.size() == 1)
   147         if (!dir.size() && 
m_mesh->m_spaceDim == 2 && 
m_mesh->m_cad)
   150                 m_mesh->m_cad->GetPeriodicTranslationVector(surf1, surf2);
   151             NekDouble mag = sqrt(T[0] * T[0] + T[1] * T[1]);
   159             if (dir != 
"x" && dir != 
"y" && dir != 
"z")
   161                 cerr << 
"WARNING: dir must be set to either x, y or z. "   162                     << 
"Skipping periodic alignment." << endl;
   166             vec[0] = (dir == 
"x") ? 1.0 : 0.0;
   167             vec[1] = (dir == 
"y") ? 1.0 : 0.0;
   168             vec[2] = (dir == 
"z") ? 1.0 : 0.0;
   171     else if (tmp1.size() == 3)
   173         vec[0] = boost::lexical_cast<
NekDouble>(tmp1[0]);
   174         vec[1] = boost::lexical_cast<
NekDouble>(tmp1[1]);
   175         vec[2] = boost::lexical_cast<
NekDouble>(tmp1[2]);
   179         ASSERTL0(
false,
"expected three components or letter for direction");
   182     auto it1 = 
m_mesh->m_composite.find(surf1);
   183     auto it2 = 
m_mesh->m_composite.find(surf2);
   185     if (it1 == 
m_mesh->m_composite.end())
   187         cerr << 
"WARNING: Couldn't find surface " << surf1
   188              << 
". Skipping periodic alignment." << endl;
   192     if (it2 == 
m_mesh->m_composite.end())
   194         cerr << 
"WARNING: Couldn't find surface " << surf2 << 
", "   195              << 
"skipping periodic alignment." << endl;
   202     if (c1->m_items.size() != c2->m_items.size())
   204         cerr << 
"WARNING: Surfaces " << surf1 << 
" and " << surf2
   205              << 
" have different numbers of elements. Skipping periodic"   206              << 
" alignment." << endl;
   210     c1->m_reorder = 
false;
   211     c2->m_reorder = 
false;
   213     map<int, pair<FaceSharedPtr, vector<int> > > perFaces;
   216     map<int, Node> centroidMap;
   217     for (
int i = 0; i < c2->m_items.size(); ++i)
   220         for (
int j = 0; j < c2->m_items[i]->GetVertexCount(); ++j)
   222             centroid += *(c2->m_items[i]->GetVertex(j));
   224         centroid /= (
NekDouble)c2->m_items[i]->GetVertexCount();
   229             centroid.
Rotate(dir,rotangle);
   232         centroidMap[i] = centroid;
   235     std::unordered_set<int> elmtDone;
   236     map<int, int> elmtPairs;
   237     map<int, int> vertCheck;
   239     for (
int i = 0; i < c1->m_items.size(); ++i)
   242         for (
int j = 0; j < c1->m_items[i]->GetVertexCount(); ++j)
   244             centroid += *(c1->m_items[i]->GetVertex(j));
   246         centroid /= (
NekDouble)c1->m_items[i]->GetVertexCount();
   250         for (
auto &it : centroidMap)
   252             if (elmtDone.count(it.first) > 0)
   257             Node dx = it.second - centroid;
   261                 match = (sqrt(dx.
abs2())< tol);
   265                 match = (fabs(fabs(dx.
m_x * vec[0] + dx.
m_y * vec[1] +
   267                               sqrt(dx.
abs2()) - 1.0) < tol);
   277                     id1 = c1->m_items[i]->GetEdgeLink()->
m_id;
   278                     id2 = c2->m_items[it.first]->GetEdgeLink()->m_id;
   282                     id1 = c1->m_items[i]->GetFaceLink()->m_id;
   283                     id2 = c2->m_items[it.first]->GetFaceLink()->m_id;
   286                 elmtDone.insert(it.first);
   287                 elmtPairs[i] = it.first;
   290                 int nVerts = c1->m_items[i]->GetVertexCount();
   291                 vector<int> perVerts(nVerts, 0), perVertsInv(nVerts, 0);
   295                     for (
int k = 0; k < nVerts; ++k)
   298                             c1->m_items[i]->GetFaceLink()->m_vertexList[k];
   302                         for (l = 0; l < nVerts; ++l)
   311                                 n2tmp.
Rotate(dir,rotangle);
   312                                 Node dn = n2tmp - *n1;
   314                                 match = (dnabs< tol);
   315                                 mindn  = (dnabs < mindn)? dnabs:mindn; 
   324                                                        sqrt(dn.
abs2()) - 1.0); 
   325                                 match = (dnabs < tol); 
   326                                 mindn  = (dnabs < mindn)? dnabs:mindn;                                 
   336                                 if (vertCheck.count(id1) == 0)
   338                                     vertCheck[id1] = id2;
   343                                              "Periodic vertex already "   350                                  "Could not identify periodic vertices, nearest distance was " + boost::lexical_cast<string>(mindn));
   353                     int tot1 = 0, tot2 = 0;
   354                     for (
int k = 0; k < nVerts; ++k)
   357                         tot2 += perVertsInv[k];
   359                     ASSERTL0(tot1 == nVerts * (nVerts - 1) / 2 &&
   360                                  tot2 == nVerts * (nVerts - 1) / 2,
   361                              "Error identifying periodic vertices");
   366                     perFaces[id1] = make_pair(
   367                         c2->m_items[it.first]->GetFaceLink(), perVerts);
   369                         make_pair(c1->m_items[i]->GetFaceLink(), perVertsInv);
   378             cerr << 
"WARNING: Could not find matching edge for surface "   379                  << 
"element " << c1->m_items[i]->GetId() << 
". "   380                  << 
"Skipping periodic alignment." << endl;
   386     vector<ElementSharedPtr> tmp = c2->m_items;
   388     for (
int i = 0; i < tmp.size(); ++i)
   390         c2->m_items[i] = tmp[elmtPairs[i]];
 
#define ASSERTL0(condition, msg)
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation. 
NEKMESHUTILS_EXPORT NekDouble abs2() const
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters. 
NekDouble m_y
Y-coordinate. 
MeshSharedPtr m_mesh
Mesh object. 
std::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh. 
Represents a point in the domain. 
std::shared_ptr< Node > NodeSharedPtr
NEKMESHUTILS_EXPORT void ReorderPrisms(PerMap &perFaces)
Reorder node IDs so that prisms and tetrahedra are aligned correctly. 
std::pair< ModuleType, std::string > ModuleKey
Represents a command-line configuration option. 
void Rotate(std::string dir, NekDouble angle)
std::map< std::string, ConfigOption > m_config
List of configuration values. 
Interpreter class for the evaluation of mathematical expressions. 
NekDouble m_x
X-coordinate. 
Abstract base class for processing modules. 
virtual void Process()
Write mesh to output file. 
virtual ~ProcessPerAlign()
Destructor. 
std::shared_ptr< Composite > CompositeSharedPtr
Shared pointer to a composite. 
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory. 
NekDouble m_z
Z-coordinate. 
std::pair< ModuleType, std::string > ModuleKey
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
ModuleFactory & GetModuleFactory()