37#include <boost/geometry.hpp>
38#include <boost/geometry/geometries/box.hpp>
39#include <boost/geometry/geometries/point.hpp>
40#include <boost/geometry/index/rtree.hpp>
48namespace bg = boost::geometry;
49namespace bgi = boost::geometry::index;
59 "Extract an isocontour of fieldid variable and at "
60 "value fieldvalue, Optionally fieldstr can be "
61 "specified for a string defiition or smooth for "
68 ConfigOption(
false,
"NotSet",
"string of isocontour to be extracted");
70 "name for isocontour if fieldstr "
71 "specified, default is isocon");
80 "Globally condense contour to unique "
84 "Smooth isocontour (might require "
89 "Number of smoothing cycle, default = "
94 "Postive diffusion coefficient "
95 "(0 < lambda < 1), default = 0.5");
99 "Negative diffusion coefficient "
100 "(0 < mu < 1), default = 0.505");
104 "Remove contours with less than specified number of triangles."
105 "Only valid with GlobalCondense or Smooth options.");
116 bool verbose = (
m_f->m_verbose &&
m_f->m_comm->TreatAsRankZero());
118 vector<IsoSharedPtr> iso;
120 ASSERTL0(
m_f->m_fieldPts.get(),
"Should have m_fieldPts for IsoContour.");
127 cout <<
"\t Process read iso from Field Pts" << endl;
136 string fieldName =
m_config[
"fieldname"].as<
string>();
137 m_f->m_variables.push_back(fieldName);
140 if (
m_f->m_fieldPts->GetNpoints() == 0)
150 fieldid =
m_f->m_fieldPts->GetNFields();
156 string varstr =
"x y z";
157 vector<Array<OneD, const NekDouble>> interpfields;
159 for (
int i = 0; i <
m_f->m_fieldPts->GetDim(); ++i)
161 interpfields.push_back(
m_f->m_fieldPts->GetPts(i));
163 for (
int i = 0; i <
m_f->m_fieldPts->GetNFields(); ++i)
165 varstr +=
" " +
m_f->m_fieldPts->GetFieldName(i);
166 interpfields.push_back(
m_f->m_fieldPts->GetPts(i + 3));
170 std::string str =
m_config[
"fieldstr"].as<
string>();
173 strEval.
Evaluate(ExprId, interpfields, pts);
177 string fieldName =
m_config[
"fieldname"].as<
string>();
179 m_f->m_fieldPts->AddField(pts, fieldName);
184 "fieldid must be specified");
185 fieldid =
m_config[
"fieldid"].as<
int>();
189 "fieldvalue must be specified");
196 ASSERTL0(
false,
"PtsType not supported for isocontour.");
200 bool smoothing =
m_config[
"smooth"].as<
bool>();
201 bool globalcondense =
m_config[
"globalcondense"].as<
bool>();
206 cout <<
"\t Process global condense ..." << endl;
208 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
211 g_iso->GlobalCondense(iso, verbose);
214 iso.push_back(g_iso);
223 cout <<
"\t Process Contour smoothing ..." << endl;
227 int niter =
m_config[
"smoothiter"].as<
int>();
230 for (
int i = 0; i < iso.size(); ++i)
232 iso[i]->Smooth(niter, lambda, -mu);
241 ss << cpuTime <<
"s";
242 cout <<
"\t Process smooth CPU Time: " << setw(8) << left
249 if ((mincontour =
m_config[
"removesmallcontour"].as<int>()))
251 vector<IsoSharedPtr> new_iso;
255 cout <<
"\t Identifying separate regions [." << flush;
257 for (
int i = 0; i < iso.size(); ++i)
259 iso[i]->SeparateRegions(new_iso, mincontour,
m_f->m_verbose);
264 cout <<
"]" << endl << flush;
283 if (((cx[0] - cx[1]) == 0.0) && ((cy[0] - cy[1]) == 0.0) &&
284 ((cz[0] - cz[1]) == 0.0))
286 if (((cx[2] - cx[3]) == 0.0) && ((cy[2] - cy[3]) == 0.0) &&
287 ((cz[2] - cz[3]) == 0.0))
305void ThreeSimilar(
const int i,
const int j,
const int k,
int &pr,
int &ps)
364 ASSERTL0(
false,
"Error in 5-point triangulation in ThreeSimilar");
372 vector<IsoSharedPtr> returnval;
374 int coordim =
m_f->m_fieldPts->GetDim();
375 int nfields =
m_f->m_fieldPts->GetNFields() + coordim;
378 "This methods is currently only set up for 3D fields");
379 ASSERTL1(coordim + fieldid < nfields,
380 "field id is larger than number contained in FieldPts");
382 m_f->m_fieldPts->GetPts(fields);
386 int i, j, k, ii, jj, kk, r, s, n, counter, boolean;
389 for (i = 1; i < nfields; ++i)
391 intfields[i] = intfields[i - 1] + 5;
397 vector<Array<OneD, int>> ptsConn;
398 m_f->m_fieldPts->GetConnectivity(ptsConn);
400 for (
int zone = 0; zone < ptsConn.size(); ++zone)
406 int nelmt = ptsConn[zone].size() / (coordim + 1);
410 for (n = 0, i = 0; i < nelmt; ++i)
413 if (!(((c[conn[i * 4]] > val) && (c[conn[i * 4 + 1]] > val) &&
414 (c[conn[i * 4 + 2]] > val) && (c[conn[i * 4 + 3]] > val)) ||
415 ((c[conn[i * 4]] < val) && (c[conn[i * 4 + 1]] < val) &&
416 (c[conn[i * 4 + 2]] < val) && (c[conn[i * 4 + 3]] < val))))
421 for (counter = 0, j = 0; j <= 2; j++)
423 for (k = j + 1; k <= 3; k++)
425 if (((c[conn[i * 4 + j]] >= val) &&
426 (val >= c[conn[i * 4 + k]])) ||
427 ((c[conn[i * 4 + j]] <= val) &&
428 (val <= c[conn[i * 4 + k]])))
434 NekDouble factor = (val - cj) / (ck - cj);
436 if (fabs(cj - ck) > 1e-12)
439 for (
int f = 0; f < nfields; ++f)
445 intfields[f][counter] =
446 fields[f][conn[4 * i + j]] +
447 factor * (fields[f][conn[4 * i + k]] -
448 fields[f][conn[4 * i + j]]);
460 iso->ResizeFields(3 * n);
462 for (j = 0; j < 3; ++j)
464 iso->SetFields(3 * (n - 1) + j, intfields, j);
469 iso->ResizeFields(3 * n);
471 for (j = 0; j < 3; ++j)
473 iso->SetFields(3 * (n - 2) + j, intfields, j);
474 iso->SetFields(3 * (n - 1) + j, intfields, j + 1);
479 iso->ResizeFields(3 * n);
482 for (ii = 0; ii <= 2; ii++)
484 for (jj = ii + 1; jj <= 3; jj++)
486 for (kk = jj + 1; kk <= 4; kk++)
488 if ((((cx[ii] - cx[jj]) == 0.0) &&
489 ((cy[ii] - cy[jj]) == 0.0) &&
490 ((cz[ii] - cz[jj]) == 0.0)) &&
491 (((cx[ii] - cx[kk]) == 0.0) &&
492 ((cy[ii] - cy[kk]) == 0.0) &&
493 ((cz[ii] - cz[kk]) == 0.0)))
498 iso->SetFields(3 * (n - 1), intfields,
500 iso->SetFields(3 * (n - 1) + 1,
502 iso->SetFields(3 * (n - 1) + 2,
517 iso->SetFields(3 * (n - 1), intfields, 0);
518 iso->SetFields(3 * (n - 1) + 1, intfields, 2);
519 iso->SetFields(3 * (n - 1) + 2, intfields, r);
533 returnval.push_back(iso);
543 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
552 for (
int i = 0; i < iso.size(); ++i)
554 npts += iso[i]->GetNVert();
563 for (
int i = 0; i < iso.size(); ++i)
565 for (
int j = 0; j < iso[i]->GetNVert(); ++j, ++cnt)
567 newfields[0][cnt] = iso[i]->GetX(j);
568 newfields[1][cnt] = iso[i]->GetY(j);
569 newfields[2][cnt] = iso[i]->GetZ(j);
574 for (
int f = 0; f < nfields - 3; ++f)
579 for (
int i = 0; i < iso.size(); ++i)
581 for (
int j = 0; j < iso[i]->GetNVert(); ++j, ++cnt)
583 newfields[f + 3][cnt] = iso[i]->GetFields(f, j);
588 m_f->m_fieldPts->SetPts(newfields);
591 vector<Array<OneD, int>> ptsConn;
592 m_f->m_fieldPts->GetConnectivity(ptsConn);
595 for (
int i = 0; i < iso.size(); ++i)
597 int ntris = iso[i]->GetNTris();
600 for (
int j = 0; j < 3 * ntris; ++j)
602 conn[j] = cnt + iso[i]->GetVId(j);
604 ptsConn.push_back(conn);
605 cnt += iso[i]->GetNVert();
607 m_f->m_fieldPts->SetConnectivity(ptsConn);
614 "Assume input is from ePtsTriBlock");
617 int dim =
m_f->m_fieldPts->GetDim();
618 int nfields =
m_f->m_fieldPts->GetNFields() + dim;
620 m_f->m_fieldPts->GetPts(fieldpts);
621 vector<Array<OneD, int>> ptsConn;
622 m_f->m_fieldPts->GetConnectivity(ptsConn);
625 for (
int c = 0; c < ptsConn.size(); ++c)
631 nelmt = ptsConn[c].size() / 3;
633 iso->SetNTris(nelmt);
634 iso->ResizeVId(3 * nelmt);
638 for (
int i = 0; i < ptsConn[c].size(); ++i)
640 int cid = ptsConn[c][i] - cnt;
642 nvert = max(cid, nvert);
646 iso->SetNVert(nvert);
647 iso->ResizeFields(nvert);
650 for (
int i = 0; i < nvert; ++i)
652 iso->SetFields(i, fieldpts, i + cnt);
655 isovec.push_back(iso);
663 vector<IsoVertex> vert;
682 for (cnt = 0, i = 0; i < 3; ++i)
687 for (
int f = 0; f <
m_fields.size(); ++f)
699 for (j = 0; j < 3; ++j)
705 auto pt =
find(vert.begin(), vert.end(), v);
706 if (pt != vert.end())
708 m_vid[3 * i + j] = pt[0].m_id;
714 for (
int f = 0; f <
m_fields.size(); ++f)
728 for (i = 0, cnt = 0; i <
m_ntris;)
735 for (j = 3 * i; j < 3 * (
m_ntris - 1); ++j)
753 for (
int f = 0; f <
m_fields.size(); ++f)
760 m_x[i] = vert[i].m_x;
761 m_y[i] = vert[i].m_y;
762 m_z[i] = vert[i].m_z;
763 for (
int f = 0; f <
m_fields.size(); ++f)
765 m_fields[f][i] = vert[i].m_fields[f];
772 typedef bg::model::point<NekDouble, 3, bg::cs::cartesian> BPoint;
773 typedef std::pair<BPoint, unsigned int> PointPair;
777 int niso = iso.size();
790 for (i = 0; i < niso; ++i)
801 for (i = 0; i < niso; ++i)
809 vector<vector<int>> isocon;
811 vector<int> global_to_unique_map;
812 global_to_unique_map.resize(
m_nvert);
814 vector<pair<int, int>> global_to_iso_map;
815 global_to_iso_map.resize(
m_nvert);
819 std::vector<PointPair> inPoints;
820 for (i = 0; i < niso; ++i)
822 for (id1 = 0; id1 < iso[i]->m_nvert; ++id1)
824 inPoints.push_back(PointPair(
825 BPoint(iso[i]->
m_x[id1], iso[i]->
m_y[id1], iso[i]->
m_z[id1]),
827 global_to_unique_map[id2] = id2;
828 global_to_iso_map[id2] = make_pair(i, id1);
835 cout <<
"\t Process building tree ..." << endl;
839 bgi::rtree<PointPair, bgi::rstar<16>> rtree;
840 rtree.insert(inPoints.begin(), inPoints.end());
843 int unique_index = 0;
853 BPoint queryPoint = inPoints[i].first;
857 if (global_to_unique_map[i] < unique_index)
863 std::vector<PointPair> result;
864 rtree.query(bgi::nearest(queryPoint, 10),
865 std::back_inserter(result));
870 for (id1 = 0; id1 < result.size(); ++id1)
872 NekDouble dist = bg::distance(queryPoint, result[id1].first);
875 id2 = result[id1].second;
878 if (global_to_unique_map[id2] < unique_index)
880 new_index = global_to_unique_map[id2];
886 new_index = unique_index;
891 global_to_unique_map[i] = new_index;
892 for (
auto &it : samept)
894 global_to_unique_map[it] = new_index;
909 for (n = 0; n < niso; ++n)
911 for (i = 0; i < iso[n]->m_ntris; ++i, nelmt++)
913 for (j = 0; j < 3; ++j)
915 m_vid[3 * nelmt + j] =
916 global_to_unique_map[iso[n]->m_vid[3 * i + j] + cnt];
919 cnt += iso[n]->m_nvert;
929 for (i = 0; i < iso[0]->m_fields.size(); ++i)
934 for (n = 0; n < global_to_unique_map.size(); ++n)
937 m_x[global_to_unique_map[n]] = bg::get<0>(inPoints[n].first);
938 m_y[global_to_unique_map[n]] = bg::get<1>(inPoints[n].first);
939 m_z[global_to_unique_map[n]] = bg::get<2>(inPoints[n].first);
941 int isoid = global_to_iso_map[n].first;
942 int ptid = global_to_iso_map[n].second;
943 for (j = 0; j <
m_fields.size(); ++j)
945 m_fields[j][global_to_unique_map[n]] =
946 iso[isoid]->m_fields[j][ptid];
979 vector<vector<int>> adj, vertcon;
980 vector<vector<NekDouble>> wght;
986 for (j = 0; j < 3; ++j)
988 vertcon[
m_vid[3 * i + j]].push_back(i);
999 for (
auto &ipt : vertcon[i])
1001 for (j = 0; j < 3; ++j)
1004 if (
m_vid[3 * ipt + j] != i)
1007 for (k = 0; k < adj[i].size(); ++k)
1009 if (adj[i][k] ==
m_vid[3 * ipt + j])
1015 if (k == adj[i].size())
1017 adj[i].push_back(
m_vid[3 * ipt + j]);
1028 for (j = 0; j < adj[i].size(); ++j)
1030 wght[i].push_back(
w);
1039 for (iter = 0; iter < n_iter; iter++)
1044 del_v[0] = del_v[1] = del_v[2] = 0.0;
1045 for (j = 0; j < adj[i].size(); ++j)
1047 del_v[0] = del_v[0] + (
m_x[adj[i][j]] -
m_x[i]) * wght[i][j];
1048 del_v[1] = del_v[1] + (
m_y[adj[i][j]] -
m_y[i]) * wght[i][j];
1049 del_v[2] = del_v[2] + (
m_z[adj[i][j]] -
m_z[i]) * wght[i][j];
1052 xtemp[i] =
m_x[i] + del_v[0] * lambda;
1053 ytemp[i] =
m_y[i] + del_v[1] * lambda;
1054 ztemp[i] =
m_z[i] + del_v[2] * lambda;
1060 del_v[0] = del_v[1] = del_v[2] = 0;
1061 for (j = 0; j < adj[i].size(); ++j)
1064 del_v[0] + (xtemp[adj[i][j]] - xtemp[i]) * wght[i][j];
1066 del_v[1] + (ytemp[adj[i][j]] - ytemp[i]) * wght[i][j];
1068 del_v[2] + (ztemp[adj[i][j]] - ztemp[i]) * wght[i][j];
1071 m_x[i] = xtemp[i] + del_v[0] * mu;
1072 m_y[i] = ytemp[i] + del_v[1] * mu;
1073 m_z[i] = ztemp[i] + del_v[2] * mu;
1090 for (j = 0; j < 3; ++j)
1092 vertcon[
m_vid[3 * i + j]].push_back(i);
1107 k,
m_nvert,
"Separating regions", progcnt);
1110 if (vidregion[k] == -1)
1112 vidregion[k] = ++nregions;
1115 for (
auto &ipt : vertcon[k])
1117 for (i = 0; i < 3; ++i)
1119 if (vidregion[
id =
m_vid[3 * ipt + i]] == -1)
1121 tocheck.push_back(
id);
1122 vidregion[id] = nregions;
1129 while (tocheck.size())
1131 auto cid = tocheck.begin();
1132 while (cid != tocheck.end())
1136 for (
auto &ipt : vertcon[*cid])
1138 for (i = 0; i < 3; ++i)
1140 if (vidregion[
id =
m_vid[3 * ipt + i]] == -1)
1142 tocheck.push_back(
id);
1143 vidregion[id] = nregions;
1149 tocheck.pop_front();
1163 nvert[vidregion[i]] += 1;
1169 nelmt[vidregion[
m_vid[3 * i]]] += 1;
1174 for (
int n = 0; n < nregions; ++n)
1176 if (nelmt[n] > minsize)
1181 iso->m_ntris = nelmt[n];
1184 iso->m_nvert = nvert[n];
1185 iso->m_x.resize(nvert[n]);
1186 iso->m_y.resize(nvert[n]);
1187 iso->m_z.resize(nvert[n]);
1189 iso->m_fields.resize(nfields);
1190 for (i = 0; i < nfields; ++i)
1192 iso->m_fields[i].resize(nvert[n]);
1200 if (vidregion[i] == n)
1209 if (vidregion[
m_vid[3 * i]] == n)
1211 for (j = 0; j < 3; ++j)
1213 iso->m_vid[3 * cnt + j] = vidmap[
m_vid[3 * i + j]];
1215 iso->m_x[vidmap[
m_vid[3 * i + j]]] =
1217 iso->m_y[vidmap[
m_vid[3 * i + j]]] =
1219 iso->m_z[vidmap[
m_vid[3 * i + j]]] =
1222 for (k = 0; k < nfields; ++k)
1224 iso->m_fields[k][vidmap[
m_vid[3 * i + j]]] =
1232 WARNINGL0(cnt == nelmt[n],
"Number of elements do not match");
1233 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)
static ModuleKey className
~ProcessIsoContour() override
void ResetFieldPts(std::vector< IsoSharedPtr > &iso)
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
void v_Process(po::variables_map &vm) override
Write mesh to output file.
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)
std::vector< double > w(NPUPPER)
void Zero(int n, T *x, const int incx)
Zero vector.
Represents a command-line configuration option.