37 #include <boost/core/ignore_unused.hpp>
38 #include <boost/geometry.hpp>
39 #include <boost/geometry/geometries/point.hpp>
40 #include <boost/geometry/geometries/box.hpp>
41 #include <boost/geometry/index/rtree.hpp>
48 #include <boost/math/special_functions/fpclassify.hpp>
50 namespace bg = boost::geometry;
51 namespace bgi = boost::geometry::index;
63 ProcessIsoContour::create,
64 "Extract an isocontour of fieldid variable and at "
65 "value fieldvalue, Optionally fieldstr can be "
66 "specified for a string defiition or smooth for "
74 "string of isocontour to be extracted");
76 "name for isocontour if fieldstr "
77 "specified, default is isocon");
80 "field id to extract");
83 "field value to extract");
86 "Globally condense contour to unique "
90 "Smooth isocontour (might require "
94 "Number of smoothing cycle, default = "
98 "Postive diffusion coefficient "
99 "(0 < lambda < 1), default = 0.5");
102 "Negative diffusion coefficient "
103 "(0 < mu < 1), default = 0.505");
106 "Remove contours with less than specified number of triangles."
107 "Only valid with GlobalCondense or Smooth options.");
120 bool verbose = (
m_f->m_verbose &&
m_f->m_comm->TreatAsRankZero());
122 vector<IsoSharedPtr> iso;
125 "Should have m_fieldPts for IsoContour.");
132 cout <<
"\t Process read iso from Field Pts" << endl;
141 string fieldName =
m_config[
"fieldname"].as<
string>();
142 m_f->m_variables.push_back(fieldName);
145 if(
m_f->m_fieldPts->GetNpoints() == 0)
155 fieldid =
m_f->m_fieldPts->GetNFields();
161 string varstr =
"x y z";
162 vector<Array<OneD, const NekDouble> > interpfields;
164 for(
int i = 0; i <
m_f->m_fieldPts->GetDim(); ++i)
166 interpfields.push_back(
m_f->m_fieldPts->GetPts(i));
168 for(
int i = 0; i <
m_f->m_fieldPts->GetNFields(); ++i)
170 varstr +=
" " +
m_f->m_fieldPts->GetFieldName(i);
171 interpfields.push_back(
m_f->m_fieldPts->GetPts(i+3));
175 std::string str =
m_config[
"fieldstr"].as<
string>();
178 strEval.
Evaluate(ExprId, interpfields, pts);
181 string fieldName =
m_config[
"fieldname"].as<
string>();
183 m_f->m_fieldPts->AddField(pts, fieldName);
187 ASSERTL0(
m_config[
"fieldid"].as<string>() !=
"NotSet",
"fieldid must be specified");
188 fieldid =
m_config[
"fieldid"].as<
int>();
191 ASSERTL0(
m_config[
"fieldvalue"].as<string>() !=
"NotSet",
"fieldvalue must be specified");
198 ASSERTL0(
false,
"PtsType not supported for isocontour.");
202 bool smoothing =
m_config[
"smooth"].as<
bool>();
203 bool globalcondense =
m_config[
"globalcondense"].as<
bool>();
208 cout <<
"\t Process global condense ..." << endl;
210 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
213 g_iso->GlobalCondense(iso,verbose);
217 iso.push_back(g_iso);
226 cout <<
"\t Process Contour smoothing ..." << endl;
230 int niter =
m_config[
"smoothiter"].as<
int>();
233 for(
int i =0 ; i < iso.size(); ++i)
235 iso[i]->Smooth(niter,lambda,-mu);
244 ss << cpuTime <<
"s";
245 cout <<
"\t Process smooth CPU Time: " << setw(8) << left
252 if((mincontour =
m_config[
"removesmallcontour"].as<int>()))
254 vector<IsoSharedPtr> new_iso;
258 cout <<
"\t Identifying separate regions [." << flush ;
260 for(
int i =0 ; i < iso.size(); ++i)
262 iso[i]->SeparateRegions(new_iso,mincontour,
m_f->m_verbose);
267 cout <<
"]" << endl << flush ;
289 if (((cx[0]-cx[1])==0.0)&&
290 ((cy[0]-cy[1])==0.0)&&
291 ((cz[0]-cz[1])==0.0))
293 if (((cx[2]-cx[3])==0.0)&&
294 ((cy[2]-cy[3])==0.0)&&
295 ((cz[2]-cz[3])==0.0))
374 ASSERTL0(
false,
"Error in 5-point triangulation in ThreeSimilar");
383 vector<IsoSharedPtr> returnval;
385 int coordim =
m_f->m_fieldPts->GetDim();
386 int nfields =
m_f->m_fieldPts->GetNFields() + coordim;
389 "This methods is currently only set up for 3D fields");
390 ASSERTL1(coordim + fieldid < nfields,
391 "field id is larger than number contained in FieldPts");
393 m_f->m_fieldPts->GetPts(fields);
397 int i, j, k, ii, jj, kk, r, s, n, counter, boolean;
400 for(i = 1; i < nfields; ++i)
402 intfields[i] = intfields[i-1] + 5;
408 vector<Array<OneD, int> > ptsConn;
409 m_f->m_fieldPts->GetConnectivity(ptsConn);
411 for(
int zone = 0; zone < ptsConn.size(); ++zone)
417 int nelmt = ptsConn[zone].size()
422 for (n = 0, i = 0; i < nelmt; ++i)
425 if(!(((c[conn[i*4]] >val)&&(c[conn[i*4+1]]>val)&&
426 (c[conn[i*4+2]]>val)&&(c[conn[i*4+3]]>val))||
427 ((c[conn[i*4 ]]<val)&&(c[conn[i*4+1]]<val)&&
428 (c[conn[i*4+2]]<val)&&(c[conn[i*4+3]]<val))))
433 for (counter = 0, j=0; j<=2; j++)
435 for (k=j+1; k<=3; k++)
437 if (((c[conn[i*4+j]]>=val)&&
438 (val>=c[conn[i*4+k]]))||
439 ((c[conn[i*4+j]]<=val)&&
440 (val<=c[conn[i*4+k]])))
448 if(fabs(cj-ck) > 1e-12)
451 for(
int f = 0; f < nfields; ++f)
457 intfields[f][counter] =
458 fields[f][conn[4*i+j]] +
459 factor*(fields[f][conn[4*i+k]] -
460 fields[f][conn[4*i+j]]);
472 iso->ResizeFields(3*n);
474 for(j = 0; j < 3; ++j)
476 iso->SetFields(3*(n-1)+j,intfields,j);
481 iso->ResizeFields(3*n);
483 for(j = 0; j < 3; ++j)
485 iso->SetFields(3*(n-2)+j,intfields,j);
486 iso->SetFields(3*(n-1)+j,intfields,j+1);
491 iso->ResizeFields(3*n);
494 for (ii=0;ii<=2;ii++)
496 for (jj=ii+1;jj<=3;jj++)
498 for (kk=jj+1;kk<=4;kk++)
500 if((((cx[ii]-cx[jj])==0.0)&&
501 ((cy[ii]-cy[jj])==0.0)&&
502 ((cz[ii]-cz[jj])==0.0))&&
503 (((cx[ii]-cx[kk])==0.0)&&
504 ((cy[ii]-cy[kk])==0.0)&&
505 ((cz[ii]-cz[kk])==0.0)))
510 iso->SetFields(3*(n-1) ,intfields,ii);
511 iso->SetFields(3*(n-1)+1,intfields,r);
512 iso->SetFields(3*(n-1)+2,intfields,s);
526 iso->SetFields(3*(n-1) ,intfields,0);
527 iso->SetFields(3*(n-1)+1,intfields,2);
528 iso->SetFields(3*(n-1)+2,intfields,r);
542 returnval.push_back(iso);
552 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
561 for(
int i =0; i < iso.size(); ++i)
563 npts += iso[i]->GetNVert();
572 for(
int i =0; i < iso.size(); ++i)
574 for(
int j = 0; j < iso[i]->GetNVert(); ++j,++cnt)
576 newfields[0][cnt] = iso[i]->GetX(j);
577 newfields[1][cnt] = iso[i]->GetY(j);
578 newfields[2][cnt] = iso[i]->GetZ(j);
584 for(
int f = 0; f < nfields-3; ++f)
589 for(
int i =0; i < iso.size(); ++i)
591 for(
int j = 0; j < iso[i]->GetNVert(); ++j,++cnt)
593 newfields[f+3][cnt] = iso[i]->GetFields(f,j);
598 m_f->m_fieldPts->SetPts(newfields);
601 vector<Array<OneD, int> > ptsConn;
602 m_f->m_fieldPts->GetConnectivity(ptsConn);
605 for(
int i =0; i < iso.size(); ++i)
607 int ntris = iso[i]->GetNTris();
610 for(
int j = 0; j < 3*ntris; ++j)
612 conn[j] = cnt + iso[i]->GetVId(j);
614 ptsConn.push_back(conn);
615 cnt += iso[i]->GetNVert();
617 m_f->m_fieldPts->SetConnectivity(ptsConn);
624 "Assume input is from ePtsTriBlock");
627 int dim =
m_f->m_fieldPts->GetDim();
628 int nfields =
m_f->m_fieldPts->GetNFields() + dim;
630 m_f->m_fieldPts->GetPts(fieldpts);
631 vector<Array<OneD, int> > ptsConn;
632 m_f->m_fieldPts->GetConnectivity(ptsConn);
636 for(
int c = 0; c < ptsConn.size(); ++c)
642 nelmt = ptsConn[c].size()/3;
644 iso->SetNTris(nelmt);
645 iso->ResizeVId(3*nelmt);
649 for(
int i = 0; i < ptsConn[c].size(); ++i)
651 int cid = ptsConn[c][i]-cnt;
653 nvert = max(cid,nvert);
657 iso->SetNVert(nvert);
658 iso->ResizeFields(nvert);
661 for(
int i = 0; i < nvert; ++i)
663 iso->SetFields(i,fieldpts,i+cnt);
666 isovec.push_back(iso);
676 vector<IsoVertex> vert;
689 for(cnt =0, i = 0; i < 3; ++i)
694 for(
int f = 0; f <
m_fields.size(); ++f)
706 for(j = 0; j < 3; ++j)
712 auto pt =
find(vert.begin(),vert.end(),v);
715 m_vid[3*i+j] = pt[0].m_id;
721 for(
int f = 0; f <
m_fields.size(); ++f)
742 for(j = 3*i; j < 3*(
m_ntris-1); ++j)
760 for(
int f = 0; f <
m_fields.size(); ++f)
767 m_x[i] = vert[i].m_x;
768 m_y[i] = vert[i].m_y;
769 m_z[i] = vert[i].m_z;
770 for(
int f = 0; f <
m_fields.size(); ++f)
772 m_fields[f][i] = vert[i].m_fields[f];
780 typedef bg::model::point<NekDouble, 3, bg::cs::cartesian> BPoint;
781 typedef std::pair<BPoint, unsigned int> PointPair;
795 for(i = 0; i < niso; ++i)
806 for(i = 0; i < niso; ++i)
814 vector< vector<int> > isocon;
816 vector<int> global_to_unique_map;
817 global_to_unique_map.resize(
m_nvert);
819 vector< pair<int,int> > global_to_iso_map;
820 global_to_iso_map.resize(
m_nvert);
824 std::vector<PointPair> inPoints;
825 for(i = 0; i < niso; ++i)
827 for(id1 = 0; id1 < iso[i]->m_nvert; ++id1)
829 inPoints.push_back(PointPair(BPoint( iso[i]->
m_x[id1],
831 iso[i]->
m_z[id1]), id2));
832 global_to_unique_map[id2]=id2;
833 global_to_iso_map[id2] = make_pair(i,id1);
841 cout <<
"\t Process building tree ..." << endl;
845 bgi::rtree<PointPair, bgi::rstar<16> > rtree;
846 rtree.insert(inPoints.begin(), inPoints.end());
849 int unique_index = 0;
856 "Nearest verts",prog);
859 BPoint queryPoint = inPoints[i].first;
864 if(global_to_unique_map[i] < unique_index)
870 std::vector<PointPair> result;
871 rtree.query(bgi::nearest(queryPoint, 10), std::back_inserter(result));
876 for(id1 = 0; id1 < result.size(); ++id1)
878 NekDouble dist = bg::distance(queryPoint, result[id1].first);
881 id2 = result[id1].second;
884 if(global_to_unique_map[id2] <unique_index)
886 new_index = global_to_unique_map[id2];
892 new_index = unique_index;
897 global_to_unique_map[i] = new_index;
898 for(
auto &it : samept)
900 global_to_unique_map[it] = new_index;
915 for(n = 0; n < niso; ++n)
917 for(i = 0; i < iso[n]->m_ntris; ++i,nelmt++)
921 m_vid[3*nelmt+j] = global_to_unique_map[iso[n]->m_vid[3*i+j]+cnt];
924 cnt += iso[n]->m_nvert;
934 for(i = 0; i < iso[0]->m_fields.size(); ++i)
939 for(n = 0; n < global_to_unique_map.size(); ++n)
942 m_x[global_to_unique_map[n]] = bg::get<0>(inPoints[n].first);
943 m_y[global_to_unique_map[n]] = bg::get<1>(inPoints[n].first);
944 m_z[global_to_unique_map[n]] = bg::get<2>(inPoints[n].first);
946 int isoid = global_to_iso_map[n].first;
947 int ptid = global_to_iso_map[n].second;
948 for(j = 0; j <
m_fields.size(); ++j)
950 m_fields[j][global_to_unique_map[n]] = iso[isoid]->
977 vector< vector<int> > adj,vertcon;
978 vector< vector<NekDouble > > wght;
984 for(j = 0; j < 3; ++j)
986 vertcon[
m_vid[3*i+j]].push_back(i);
997 for(
auto &ipt : vertcon[i])
999 for(j = 0; j < 3; ++j)
1002 if(
m_vid[3*ipt+j] != i)
1005 for(k = 0; k < adj[i].size(); ++k)
1007 if(adj[i][k] ==
m_vid[3*ipt+j])
1013 if(k == adj[i].size())
1015 adj[i].push_back(
m_vid[3*ipt+j]);
1026 for(j = 0; j < adj[i].size(); ++j)
1028 wght[i].push_back(w);
1038 for (iter=0;iter<n_iter;iter++)
1043 del_v[0] = del_v[1] = del_v[2] = 0.0;
1044 for(j = 0; j < adj[i].size(); ++j)
1046 del_v[0] = del_v[0] + (
m_x[adj[i][j]]-
m_x[i])*wght[i][j];
1047 del_v[1] = del_v[1] + (
m_y[adj[i][j]]-
m_y[i])*wght[i][j];
1048 del_v[2] = del_v[2] + (
m_z[adj[i][j]]-
m_z[i])*wght[i][j];
1051 xtemp[i] =
m_x[i] + del_v[0] * lambda;
1052 ytemp[i] =
m_y[i] + del_v[1] * lambda;
1053 ztemp[i] =
m_z[i] + del_v[2] * lambda;
1059 del_v[0] = del_v[1] = del_v[2] = 0;
1060 for(j = 0; j < adj[i].size(); ++j)
1062 del_v[0] = del_v[0] + (xtemp[adj[i][j]]-xtemp[i])*wght[i][j];
1063 del_v[1] = del_v[1] + (ytemp[adj[i][j]]-ytemp[i])*wght[i][j];
1064 del_v[2] = del_v[2] + (ztemp[adj[i][j]]-ztemp[i])*wght[i][j];
1067 m_x[i] = xtemp[i] + del_v[0] * mu;
1068 m_y[i] = ytemp[i] + del_v[1] * mu;
1069 m_z[i] = ztemp[i] + del_v[2] * mu;
1086 for(j = 0; j < 3; ++j)
1088 vertcon[
m_vid[3*i+j]].push_back(i);
1106 if(vidregion[k] == -1)
1108 vidregion[k] = ++nregions;
1111 for(
auto &ipt : vertcon[k])
1113 for(i = 0; i < 3; ++i)
1115 if(vidregion[
id =
m_vid[3*ipt+i]] == -1)
1117 tocheck.push_back(
id);
1118 vidregion[id] = nregions;
1125 while(tocheck.size())
1127 auto cid = tocheck.begin();
1128 while(cid != tocheck.end())
1132 for(
auto &ipt : vertcon[*cid])
1134 for(i = 0; i < 3; ++i)
1136 if(vidregion[
id =
m_vid[3*ipt+i]] == -1)
1138 tocheck.push_back(
id);
1139 vidregion[id] = nregions;
1145 tocheck.pop_front();
1160 nvert[vidregion[i]] +=1;
1166 nelmt[vidregion[
m_vid[3*i]]] +=1;
1171 for(
int n = 0; n < nregions; ++n)
1173 if(nelmt[n] > minsize)
1178 iso->m_ntris = nelmt[n];
1181 iso->m_nvert = nvert[n];
1182 iso->m_x.resize(nvert[n]);
1183 iso->m_y.resize(nvert[n]);
1184 iso->m_z.resize(nvert[n]);
1186 iso->m_fields.resize(nfields);
1187 for(i = 0; i < nfields; ++i)
1189 iso->m_fields[i].resize(nvert[n]);
1198 if(vidregion[i] == n)
1207 if(vidregion[
m_vid[3*i]] == n)
1209 for(j = 0; j < 3; ++j)
1211 iso->m_vid[3*cnt+j] = vidmap[
m_vid[3*i+j]];
1217 for(k = 0; k < nfields; ++k)
1226 WARNINGL0(cnt == nelmt[n],
"Number of elements do not match");
1227 sep_iso.push_back(iso);
#define ASSERTL0(condition, msg)
#define WARNINGL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
void SeparateRegions(std::vector< std::shared_ptr< Iso > > &iso, int minsize, bool verbose)
std::vector< NekDouble > m_z
void GlobalCondense(std::vector< std::shared_ptr< Iso > > &iso, bool verbose)
std::vector< std::vector< NekDouble > > m_fields
std::vector< NekDouble > m_y
std::vector< NekDouble > m_x
void Smooth(int n_iter, NekDouble lambda, NekDouble mu)
std::vector< NekDouble > m_fields
FieldSharedPtr m_f
Field object.
std::map< std::string, ConfigOption > m_config
List of configuration values.
std::vector< IsoSharedPtr > ExtractContour(const int fieldid, const NekDouble val)
void SetupIsoFromFieldPts(std::vector< IsoSharedPtr > &isovec)
virtual void Process(po::variables_map &vm)
Write mesh to output file.
void ResetFieldPts(std::vector< IsoSharedPtr > &iso)
virtual ~ProcessIsoContour()
Abstract base class for processing modules.
Interpreter class for the evaluation of mathematical expressions.
int DefineFunction(const std::string &vlist, const std::string &expr)
Defines a function for the purposes of evaluation.
NekDouble Evaluate(const int id)
Evaluate a function which depends only on constants and/or parameters.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< Field > FieldSharedPtr
std::pair< ModuleType, std::string > ModuleKey
bool operator==(TriFaceIDs const &p1, TriFaceIDs const &p2)
void ThreeSimilar(const int i, const int j, const int k, int &pr, int &ps)
bool operator!=(const IsoVertex &x, const IsoVertex &y)
void TwoPairs(Array< OneD, NekDouble > &cx, Array< OneD, NekDouble > &cy, Array< OneD, NekDouble > &cz, int &pr)
std::shared_ptr< Iso > IsoSharedPtr
ModuleFactory & GetModuleFactory()
int PrintProgressbar(const int position, const int goal, const std::string message, int lastprogress=-1)
Prints a progressbar.
static const NekDouble kNekZeroTol
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
The above copyright notice and this permission notice shall be included.
void Zero(int n, T *x, const int incx)
Zero vector.
Represents a command-line configuration option.