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.");
118 boost::ignore_unused(vm);
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>();
176 ExprId = strEval.DefineFunction(varstr.c_str(), str);
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].num_elements()
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].num_elements()/3;
644 iso->SetNTris(nelmt);
645 iso->ResizeVId(3*nelmt);
649 for(
int i = 0; i < ptsConn[c].num_elements(); ++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;
680 if(m_condensed)
return;
683 vert.reserve(m_ntris/6);
689 for(cnt =0, i = 0; i < 3; ++i)
694 for(
int f = 0; f < m_fields.size(); ++f)
704 for(i = 1; i < m_ntris; ++i)
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)
728 m_vid[3*i+j] = v.
m_id;
735 for(i = 0,cnt=0; i < m_ntris;)
737 if((m_vid[3*i] ==m_vid[3*i+1])||
738 (m_vid[3*i] ==m_vid[3*i+2])||
739 (m_vid[3*i+1]==m_vid[3*i+2]))
742 for(j = 3*i; j < 3*(m_ntris-1); ++j)
744 m_vid[j] = m_vid[j+3];
754 m_nvert = vert.size();
760 for(
int f = 0; f < m_fields.size(); ++f)
762 m_fields[f].resize(m_nvert);
765 for(i = 0; i < m_nvert; ++i)
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;
789 if(m_condensed)
return;
795 for(i = 0; i < niso; ++i)
799 m_ntris += iso[i]->m_ntris;
806 for(i = 0; i < niso; ++i)
810 m_nvert += iso[i]->m_nvert;
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;
851 for(i = 0; i < m_nvert; ++i)
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;
910 m_nvert = unique_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;
933 m_fields.resize(iso[0]->m_fields.size());
934 for(i = 0; i < iso[0]->m_fields.size(); ++i)
936 m_fields[i].resize(m_nvert);
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;
981 vertcon.resize(m_nvert);
982 for(i = 0; i < m_ntris; ++i)
984 for(j = 0; j < 3; ++j)
986 vertcon[m_vid[3*i+j]].push_back(i);
992 wght.resize(m_nvert);
994 for(i =0; i < m_nvert; ++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]);
1023 for(i =0; i < m_nvert; ++i)
1026 for(j = 0; j < adj[i].size(); ++j)
1028 wght[i].push_back(w);
1038 for (iter=0;iter<n_iter;iter++)
1041 for(i=0;i< m_nvert;++i)
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;
1057 for(i=0;i< m_nvert;++i)
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;
1084 for(i = 0; i < m_ntris; ++i)
1086 for(j = 0; j < 3; ++j)
1088 vertcon[m_vid[3*i+j]].push_back(i);
1099 for(k = 0; k < m_nvert; ++k)
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();
1158 for(i = 0; i < m_nvert; ++i)
1160 nvert[vidregion[i]] +=1;
1164 for(i = 0; i < m_ntris; ++i)
1166 nelmt[vidregion[m_vid[3*i]]] +=1;
1171 for(
int n = 0; n < nregions; ++n)
1173 if(nelmt[n] > minsize)
1175 int nfields = m_fields.size();
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]);
1196 for(i = 0; i < m_nvert; ++i)
1198 if(vidregion[i] == n)
1205 for(i = 0; i < m_ntris; ++i)
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]];
1213 iso->m_x[vidmap[m_vid[3*i+j]]] = m_x[m_vid[3*i+j]];
1214 iso->m_y[vidmap[m_vid[3*i+j]]] = m_y[m_vid[3*i+j]];
1215 iso->m_z[vidmap[m_vid[3*i+j]]] = m_z[m_vid[3*i+j]];
1217 for(k = 0; k < nfields; ++k)
1219 iso->m_fields[k][vidmap[m_vid[3*i+j]]] = m_fields[k][m_vid[3*i+j]];
1226 WARNINGL0(cnt == nelmt[n],
"Number of elements do not match");
1227 sep_iso.push_back(iso);
#define ASSERTL0(condition, msg)
bool operator==(TriFaceIDs const &p1, TriFaceIDs const &p2)
int PrintProgressbar(const int position, const int goal, const std::string message, int lastprogress=-1)
Prints a progressbar.
std::map< std::string, ConfigOption > m_config
List of configuration values.
Represents a command-line configuration option.
void SetupIsoFromFieldPts(std::vector< IsoSharedPtr > &isovec)
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
std::shared_ptr< Field > FieldSharedPtr
void ThreeSimilar(const int i, const int j, const int k, int &pr, int &ps)
void TwoPairs(Array< OneD, NekDouble > &cx, Array< OneD, NekDouble > &cy, Array< OneD, NekDouble > &cz, int &pr)
bool operator!=(const IsoVertex &x, const IsoVertex &y)
static const NekDouble kNekZeroTol
std::pair< ModuleType, std::string > ModuleKey
virtual ~ProcessIsoContour()
#define WARNINGL0(condition, msg)
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void Smooth(int n_iter, NekDouble lambda, NekDouble mu)
Interpreter class for the evaluation of mathematical expressions.
virtual void Process(po::variables_map &vm)
Write mesh to output file.
void ResetFieldPts(std::vector< IsoSharedPtr > &iso)
void GlobalCondense(std::vector< std::shared_ptr< Iso > > &iso, bool verbose)
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::vector< NekDouble > m_fields
void SeparateRegions(std::vector< std::shared_ptr< Iso > > &iso, int minsize, bool verbose)
std::vector< IsoSharedPtr > ExtractContour(const int fieldid, const NekDouble val)
void Zero(int n, T *x, const int incx)
Zero vector.
Abstract base class for processing modules.
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
std::shared_ptr< Iso > IsoSharedPtr
ModuleFactory & GetModuleFactory()
FieldSharedPtr m_f
Field object.