39 #include "../MeshElements.h"
50 #define TOL_BLEND 1.0e-8
59 ProcessSpherigon::create);
93 "Number of points to add to face edges.");
95 "Tag identifying surface to process.");
97 "Curve both triangular faces of prism on boundary.");
99 "Use alternative file for Spherigon definition");
101 "Apply scaling factor to coordinates in file ");
103 "Add randowm noise to normals of amplitude AMP in specified region. input string is Amp,xmin,xmax,ymin,ymax,zmin,zmax");
142 return sqrt(tmp1*tmp1 + tmp2*tmp2 + tmp3*tmp3);
170 vector<double> &r, vector<Node> &Q,
Node &P, vector<double> &blend)
172 vector<double> tmp(r.size());
173 double totBlend = 0.0;
177 for (i = 0; i < nV; ++i)
180 tmp [i] = (Q[i]-P).abs2();
183 for (i = 0; i < nV; ++i)
185 int ip = (i+1) % nV, im = (i-1+nV) % nV;
189 blend[i] = r[i]*r[i]*(
190 r[im]*r[im]*tmp[im]/(tmp[im] + tmp[i]) +
191 r[ip]*r[ip]*tmp[ip]/(tmp[ip] + tmp[i]));
192 totBlend += blend[i];
196 for (i = 0; i < nV; ++i)
198 blend[i] /= totBlend;
230 for (
int i = 0; i < el.size(); ++i)
238 "Spherigon expansions must be lines, triangles or "
242 int nV = e->GetVertexCount();
243 vector<NodeSharedPtr> node(nV);
245 for (
int j = 0; j < nV; ++j)
247 node[j] = e->GetVertex(j);
252 if (mesh->m_spaceDim == 3)
255 Node v1 = *(node[1]) - *(node[0]);
256 Node v2 = *(node[2]) - *(node[0]);
262 Node dx = *(node[1]) - *(node[0]);
263 dx /= sqrt(dx.
abs2());
271 for (
int j = 0; j < nV; ++j)
273 nIt = mesh->m_vertexNormals.find(e->GetVertex(j)->m_id);
274 if (nIt == mesh->m_vertexNormals.end())
276 mesh->m_vertexNormals[e->GetVertex(j)->m_id] = n;
286 for (nIt = mesh->m_vertexNormals.begin();
287 nIt != mesh->m_vertexNormals.end (); ++nIt)
289 Node &n = mesh->m_vertexNormals[nIt->first];
300 "Spherigon implementation only valid in 2D/3D.");
303 boost::unordered_set<int> visitedEdges;
306 vector<ElementSharedPtr> el;
310 cout <<
"ProcessSpherigon: Smoothing mesh..." << endl;
328 string surfTag =
m_config[
"surf"].as<
string>();
329 bool prismTag =
m_config[
"BothTriFacesOnPrism"].beenSet;
333 vector<unsigned int> surfs;
335 sort(surfs.begin(), surfs.end());
337 m_mesh->m_spherigonSurfs.clear();
338 for (
int i = 0; i <
m_mesh->m_element[
m_mesh->m_expDim].size(); ++i)
341 int nSurf =
m_mesh->m_expDim == 3 ? el->GetFaceCount() :
344 for (
int j = 0; j < nSurf; ++j)
346 int bl = el->GetBoundaryLink(j);
353 vector<int> tags = bEl->GetTagList();
356 sort(tags.begin(), tags.end());
357 set_intersection(surfs.begin(), surfs.end(),
358 tags .begin(), tags .end(),
359 back_inserter(inter));
361 if (inter.size() == 1)
363 m_mesh->m_spherigonSurfs.insert(make_pair(i, j));
367 if(nSurf == 5 && prismTag)
371 int triFace = j == 1 ? 3 : 1;
372 m_mesh->m_spherigonSurfs.insert(
373 make_pair(i, triFace));
380 if (
m_mesh->m_spherigonSurfs.size() == 0)
382 cerr <<
"WARNING: Spherigon surfaces have not been defined "
383 <<
"-- ignoring smoothing." << endl;
387 if (
m_mesh->m_expDim == 3)
389 for (it =
m_mesh->m_spherigonSurfs.begin();
390 it !=
m_mesh->m_spherigonSurfs.end (); ++it)
394 vector<NodeSharedPtr> nodes = f->m_vertexList;
400 CreateInstance(eType,conf,nodes,t);
403 for (
int i = 0; i < f->m_vertexList.size(); ++i)
405 elmt->SetVertex(i, f->m_vertexList[i]);
407 for (
int i = 0; i < f->m_edgeList.size(); ++i)
409 elmt->SetEdge(i, f->m_edgeList[i]);
417 for (it =
m_mesh->m_spherigonSurfs.begin();
418 it !=
m_mesh->m_spherigonSurfs.end (); ++it)
422 vector<NodeSharedPtr> nodes;
426 nodes.push_back(edge->m_n1);
427 nodes.push_back(edge->m_n2);
431 CreateInstance(eType,conf,nodes,t);
434 elmt->SetVertex(0, nodes[0]);
435 elmt->SetVertex(1, nodes[1]);
436 elmt->SetEdge(0,
m_mesh->m_element[
m_mesh->m_expDim][it->first]->
437 GetEdge(it->second));
444 ASSERTL0(
false,
"Spherigon expansions must be 2/3 dimensional");
450 bool normalsGenerated =
false;
453 std::string normalfile =
m_config[
"usenormalfile"].as<
string>();
454 if(normalfile.compare(
"NoFile") != 0)
460 cout <<
"Inputing normal file: " << normalfile <<
" with scaling of " << scale << endl;
466 inply.open(normalfile.c_str());
467 ASSERTL0(inply,
string(
"Could not open input ply file: ") +
472 plyfile = boost::shared_ptr<InputPly>(
new InputPly(m));
473 plyfile->ReadPly(inply,scale);
474 plyfile->ProcessVertices();
482 Node minx(0,0.0,0.0,0.0), tmp,tmpsav;
485 map<int,NodeSharedPtr> surfverts;
488 for (
int i = 0; i < el.size(); ++i)
491 int nV = e->GetVertexCount();
492 for (
int j = 0; j < nV; ++j)
494 int id = e->GetVertex(j)->m_id;
495 surfverts[id] = e->GetVertex(j);
508 cout <<
"\t Processing surface normals " << endl;
511 map<int,int> locnorm;
512 for(vIt = surfverts.begin(); vIt != surfverts.end(); ++vIt,++cnt)
516 for(j = 0, it = plymesh->m_vertexSet.begin(); it != plymesh->m_vertexSet.end(); ++it, ++j)
518 tmp = *(vIt->second)- *(*it);
524 cntmin = (*it)->m_id;
528 locnorm[cntmin] = vIt->first;
530 ASSERTL1(cntmin < plymesh->m_vertexNormals.size(),
"cntmin is out of range");
531 m_mesh->m_vertexNormals[vIt->first] = plymesh->m_vertexNormals[cntmin];
536 cout <<
"\t end of processing surface normals " << endl;
538 normalsGenerated =
true;
540 else if (
m_mesh->m_vertexNormals.size() == 0)
543 normalsGenerated =
true;
548 std::string normalnoise =
m_config[
"normalnoise"].as<
string>();
549 if(normalnoise.compare(
"NotSpecified") != 0)
551 vector<NekDouble> values;
554 int nvalues = values.size()/2;
560 cout <<
"\t adding noise to normals of amplitude "<< amp <<
" in range: ";
561 for(
int i = 0; i < nvalues; ++i)
563 cout << values[2*i+1] <<
"," << values[2*i+2] <<
" ";
569 map<int,NodeSharedPtr> surfverts;
572 for (
int i = 0; i < el.size(); ++i)
575 int nV = e->GetVertexCount();
576 for (
int j = 0; j < nV; ++j)
578 int id = e->GetVertex(j)->m_id;
579 surfverts[id] = e->GetVertex(j);
583 for(vIt = surfverts.begin(); vIt != surfverts.end(); ++vIt)
585 bool AddNoise =
false;
587 for(
int i = 0; i < nvalues; ++i)
594 if(((vIt->second)->m_x > values[2*i+1])&&((vIt->second)->m_x < values[2*i+2]))
602 if(((vIt->second)->m_x > values[2*i+1])&&
603 ((vIt->second)->m_x < values[2*i+2])&&
604 ((vIt->second)->m_y > values[2*i+3])&&
605 ((vIt->second)->m_y < values[2*i+4]))
613 if(((vIt->second)->m_x > values[2*i+1])&&
614 ((vIt->second)->m_x < values[2*i+2])&&
615 ((vIt->second)->m_y > values[2*i+3])&&
616 ((vIt->second)->m_y < values[2*i+4])&&
617 ((vIt->second)->m_z > values[2*i+5])&&
618 ((vIt->second)->m_z < values[2*i+6]))
630 Node rvec(0,rand(),rand(),rand());
631 rvec *= values[0]/sqrt(rvec.
abs2());
633 Node normal =
m_mesh->m_vertexNormals[vIt->first];
636 normal /= sqrt(normal.abs2());
638 m_mesh->m_vertexNormals[vIt->first] = normal;
647 int nquad =
m_mesh->m_spaceDim == 3 ? nq*nq : nq;
656 ASSERTL0(nq > 2,
"Number of points must be greater than 2.");
671 stdtri->GetNodalPoints(xnodal, ynodal);
673 int edgeMap[3][4][2] = {
674 {{0, 1}, {-1, -1}, {-1, -1 }, {-1, -1}},
675 {{0, 1}, {nq-1, nq}, {nq*(nq-1), -nq}, {-1, -1}},
676 {{0, 1}, {nq-1, nq}, {nq*nq-1, -1 }, {nq*(nq-1), -nq}}
679 int vertMap[3][4][2] = {
680 {{0, 1}, {0, 0}, {0, 0}, {0, 0}},
681 {{0, 1}, {1, 2}, {2, 3}, {0, 0}},
682 {{0, 1}, {1, 2}, {2, 3}, {3, 0}},
685 for (
int i = 0; i < el.size(); ++i)
701 e->GetGeom(
m_mesh->m_spaceDim));
705 seg->GetCoords(x,y,z);
719 tri->GetCoords(xc,yc,zc);
722 for (
int j = 0; j < nquad; ++j)
724 coord[0] = xnodal[j];
725 coord[1] = ynodal[j];
726 x[j] = stdtri->PhysEvaluate(coord, xc);
729 for (
int j = 0; j < nquad; ++j)
731 coord[0] = xnodal[j];
732 coord[1] = ynodal[j];
733 y[j] = stdtri->PhysEvaluate(coord, yc);
736 for (
int j = 0; j < nquad; ++j)
738 coord[0] = xnodal[j];
739 coord[1] = ynodal[j];
740 z[j] = stdtri->PhysEvaluate(coord, zc);
751 quad->GetCoords(x,y,z);
756 ASSERTL0(
false,
"Unknown expansion type.");
760 if (
m_mesh->m_spaceDim == 2)
766 int nV = e->GetVertexCount();
768 for (
int j = 0; j < nV; ++j)
770 v.push_back(*(e->GetVertex(j)));
771 ASSERTL1(
m_mesh->m_vertexNormals.count(v[j].m_id) != 0,
"Normal has not been defined");
772 vN.push_back(
m_mesh->m_vertexNormals[v[j].m_id]);
775 vector<Node> tmp (nV);
776 vector<double> r (nV);
779 vector<Node> Qp (nV);
780 vector<double> blend(nV);
781 vector<Node> out (nquad);
784 double segLength = sqrt((v[0] - v[1]).abs2());
787 for (
int j = 0; j < nquad; ++j)
789 Node P(0, x[j], y[j], z[j]);
794 if (
m_mesh->m_spaceDim == 2)
799 r[0] = sqrt((P - v[0]).abs2()) / segLength;
800 r[0] = max(min(1.0, r[0]), 0.0);
804 N = vN[0]*r[0] + vN[1]*r[1];
806 else if (
m_mesh->m_spaceDim == 3)
808 for (
int k = 0; k < nV; ++k)
816 for (
int k = 0; k < nV; ++k)
819 for (
int l = 0; l < nV-2; ++l)
828 for (
int k = 0; k < nV; ++k)
838 for (
int k = 0; k < nV; ++k)
843 K [k] = P+N*((v[k]-P).dot(N));
844 tmp1 = (v[k]-K[k]).dot(vN[k]) / (1.0 + N.
dot(vN[k]));
845 Q [k] = K[k] + N*tmp1;
846 Qp[k] = v[k] - N*((v[k]-P).dot(N));
855 for (
int k = 0; k < nV; ++k)
865 int offset = (int)e->GetConf().m_e-2;
867 for (
int edge = 0; edge < e->GetEdgeCount(); ++edge)
869 eIt = visitedEdges.find(e->GetEdge(edge)->m_id);
870 if (eIt == visitedEdges.end())
872 bool reverseEdge = !(v[vertMap[offset][edge][0]] ==
873 *(e->GetEdge(edge)->m_n1));
876 e->GetEdge(edge)->m_edgeNodes.clear();
880 for (
int j = 1; j < nq-1; ++j)
882 int v = edgeMap[offset][edge][0] +
883 j*edgeMap[offset][edge][1];
884 e->GetEdge(edge)->m_edgeNodes.push_back(
890 for (
int j = 0; j < nq-2; ++j)
892 int v = 3 + edge*(nq-2) + j;
893 e->GetEdge(edge)->m_edgeNodes.push_back(
900 reverse(e->GetEdge(edge)->m_edgeNodes.begin(),
901 e->GetEdge(edge)->m_edgeNodes.end());
904 e->GetEdge(edge)->m_curveType =
907 visitedEdges.insert(e->GetEdge(edge)->m_id);
912 if (
m_mesh->m_spaceDim == 3)
914 vector<NodeSharedPtr> volNodes;
918 volNodes.resize((nq-2)*(nq-2));
919 for (
int j = 1; j < nq-1; ++j)
921 for (
int k = 1; k < nq-1; ++k)
924 volNodes[(j-1)*(nq-2)+(k-1)] =
931 for (
int j = 3+3*(nq-2); j < nquad; ++j)
937 e->SetVolumeNodes(volNodes);
942 if (
m_mesh->m_expDim == 3)
946 for (it =
m_mesh->m_spherigonSurfs.begin();
947 it !=
m_mesh->m_spherigonSurfs.end (); ++it, ++elmt)
952 f->m_faceNodes = el[elmt]->GetVolumeNodes();
953 f->m_curveType = f->m_vertexList.size() == 3 ?
959 if (normalsGenerated)
961 m_mesh->m_vertexNormals.clear();
#define ASSERTL0(condition, msg)
pair< ModuleType, string > ModuleKey
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
virtual ~ProcessSpherigon()
Destructor.
void GenerateNormals(vector< ElementSharedPtr > &el, MeshSharedPtr &mesh)
Generate a set of approximate vertex normals to a surface represented by line segments in 2D and a hy...
boost::shared_ptr< QuadGeom > QuadGeomSharedPtr
boost::shared_ptr< Edge > EdgeSharedPtr
Shared pointer to an edge.
map< string, ConfigOption > m_config
List of configuration values.
Principle Modified Functions .
MeshSharedPtr m_mesh
Mesh object.
boost::shared_ptr< Face > FaceSharedPtr
Shared pointer to a face.
boost::shared_ptr< Node > NodeSharedPtr
Shared pointer to a Node.
static bool GenerateSeqVector(const char *const str, std::vector< unsigned int > &vec)
boost::shared_ptr< StdNodalTriExp > StdNodalTriExpSharedPtr
virtual void Process()
Write mesh to output file.
Gauss Radau pinned at x=-1, .
NekDouble m_x
X-coordinate.
boost::shared_ptr< Element > ElementSharedPtr
Shared pointer to an element.
Principle Orthogonal Functions .
void SuperBlend(vector< double > &r, vector< Node > &Q, Node &P, vector< double > &blend)
Calculate the blending function for spherigon implementation.
boost::shared_ptr< SegExp > SegExpSharedPtr
boost::shared_ptr< SegGeom > SegGeomSharedPtr
boost::shared_ptr< Mesh > MeshSharedPtr
Shared pointer to a mesh.
Principle Orthogonal Functions .
Defines a specification for a set of points.
boost::shared_ptr< QuadExp > QuadExpSharedPtr
NekDouble m_y
Y-coordinate.
double CrossProdMag(Node &a, Node &b)
Calculate the magnitude of the cross product .
Basic information about an element.
Represents a point in the domain.
void UnitCrossProd(Node &a, Node &b, Node &c)
boost::shared_ptr< InputPly > InputPlySharedPtr
Represents a command-line configuration option.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
NekDouble dot(const Node &pSrc) const
NekDouble m_z
Z-coordinate.
boost::shared_ptr< TriGeom > TriGeomSharedPtr
void Zero(int n, T *x, const int incx)
Zero vector.
static bool GenerateUnOrderedVector(const char *const str, std::vector< NekDouble > &vec)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Describes the specification for a Basis.
ElementFactory & GetElementFactory()
double Blend(double r)
Calculate the blending function for spherigon implementation.
1D Gauss-Lobatto-Legendre quadrature points
2D Nodal Electrostatic Points on a Triangle
ModuleFactory & GetModuleFactory()
Abstract base class for processing modules.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.
boost::shared_ptr< NodalTriExp > NodalTriExpSharedPtr