43 #include <boost/math/special_functions/fpclassify.hpp>
53 ProcessIsoContour::create,
54 "Extract an isocontour of fieldid variable and at "
55 "value fieldvalue, Optionally fieldstr can be "
56 "specified for a string defiition or smooth for "
64 "string of isocontour to be extracted");
66 "name for isocontour if fieldstr "
67 "specified, default is isocon");
70 "field id to extract");
72 "field value to extract");
75 "Globally condense contour to unique "
79 "Smooth isocontour (implies global "
82 "Number of smoothing cycle, default = "
85 "Postive diffusion coefficient "
86 "(0 < lambda < 1), default = 0.5");
88 "Negative diffusion coefficient "
89 "(0 < mu < 1), default = 0.495");
92 "Remove contours with less than specified number of triangles."
93 "Only valid with GlobalCondense or Smooth options.");
104 vector<IsoSharedPtr> iso;
114 fieldid =
m_f->m_fieldPts->GetNFields();
120 string varstr =
"x y z";
121 vector<Array<OneD, const NekDouble> > interpfields;
123 for(
int i = 0; i <
m_f->m_fieldPts->GetDim(); ++i)
125 interpfields.push_back(
m_f->m_fieldPts->GetPts(i));
127 for(
int i = 0; i <
m_f->m_fieldPts->GetNFields(); ++i)
129 varstr +=
" " +
m_f->m_fieldPts->GetFieldName(i);
130 interpfields.push_back(
m_f->m_fieldPts->GetPts(i+3));
134 std::string str =
m_config[
"fieldstr"].as<
string>();
135 ExprId = strEval.DefineFunction(varstr.c_str(), str);
137 strEval.Evaluate(ExprId, interpfields, pts);
140 string fieldName =
m_config[
"fieldname"].as<
string>();
142 m_f->m_fieldPts->AddField(pts, fieldName);
146 ASSERTL0(
m_config[
"fieldid"].as<string>() !=
"NotSet",
"fieldid must be specified");
147 fieldid =
m_config[
"fieldid"].as<
int>();
150 ASSERTL0(
m_config[
"fieldvalue"].as<string>() !=
"NotSet",
"fieldvalue must be specified");
154 bool smoothing =
m_config[
"smooth"].m_beenSet;
155 bool globalcondense =
m_config[
"globalcondense"].m_beenSet;
156 if(smoothing||globalcondense)
158 vector<IsoSharedPtr> glob_iso;
159 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
163 g_iso->globalcondense(iso);
167 int niter =
m_config[
"smoothiter"].as<
int>();
170 g_iso->smooth(niter,lambda,-mu);
174 if((mincontour =
m_config[
"removesmallcontour"].as<int>()))
176 g_iso->separate_regions(glob_iso,mincontour);
180 glob_iso.push_back(g_iso);
202 if (((cx[0]-cx[1])==0.0)&&
203 ((cy[0]-cy[1])==0.0)&&
204 ((cz[0]-cz[1])==0.0))
206 if (((cx[2]-cx[3])==0.0)&&
207 ((cy[2]-cy[3])==0.0)&&
208 ((cz[2]-cz[3])==0.0))
287 ASSERTL0(
false,
"Error in 5-point triangulation in ThreeSimilar");
296 vector<IsoSharedPtr> returnval;
298 int coordim =
m_f->m_exp[0]->GetCoordim(0);
299 int nfields =
m_f->m_fieldPts->GetNFields() + coordim;
302 "This methods is currently only set up for 3D fields");
303 ASSERTL1(coordim + fieldid < nfields,
304 "field id is larger than number contained in FieldPts");
306 m_f->m_fieldPts->GetPts(fields);
310 int i, j, k, ii, jj, kk, r, s, n, counter, boolean;
313 for(i = 1; i < nfields; ++i)
315 intfields[i] = intfields[i-1] + 5;
321 vector<Array<OneD, int> > ptsConn;
322 m_f->m_fieldPts->GetConnectivity(ptsConn);
323 for(
int zone = 0; zone < ptsConn.size(); ++zone)
329 int nelmt = ptsConn[zone].num_elements()
334 for (n = 0, i = 0; i < nelmt; ++i)
337 if(!(((c[conn[i*4]] >val)&&(c[conn[i*4+1]]>val)&&
338 (c[conn[i*4+2]]>val)&&(c[conn[i*4+3]]>val))||
339 ((c[conn[i*4 ]]<val)&&(c[conn[i*4+1]]<val)&&
340 (c[conn[i*4+2]]<val)&&(c[conn[i*4+3]]<val))))
345 for (counter = 0, j=0; j<=2; j++)
347 for (k=j+1; k<=3; k++)
349 if (((c[conn[i*4+j]]>=val)&&
350 (val>=c[conn[i*4+k]]))||
351 ((c[conn[i*4+j]]<=val)&&
352 (val<=c[conn[i*4+k]])))
360 if(fabs(cj-ck) > 1e-12)
363 for(
int f = 0; f < nfields; ++f)
369 intfields[f][counter] =
370 fields[f][conn[4*i+j]] +
371 factor*(fields[f][conn[4*i+k]] -
372 fields[f][conn[4*i+j]]);
384 iso->resize_fields(3*n);
386 for(j = 0; j < 3; ++j)
388 iso->set_fields(3*(n-1)+j,intfields,j);
393 iso->resize_fields(3*n);
395 for(j = 0; j < 3; ++j)
397 iso->set_fields(3*(n-2)+j,intfields,j);
398 iso->set_fields(3*(n-1)+j,intfields,j+1);
403 iso->resize_fields(3*n);
406 for (ii=0;ii<=2;ii++)
408 for (jj=ii+1;jj<=3;jj++)
410 for (kk=jj+1;kk<=4;kk++)
412 if((((cx[ii]-cx[jj])==0.0)&&
413 ((cy[ii]-cy[jj])==0.0)&&
414 ((cz[ii]-cz[jj])==0.0))&&
415 (((cx[ii]-cx[kk])==0.0)&&
416 ((cy[ii]-cy[kk])==0.0)&&
417 ((cz[ii]-cz[kk])==0.0)))
422 iso->set_fields(3*(n-1) ,intfields,ii);
423 iso->set_fields(3*(n-1)+1,intfields,r);
424 iso->set_fields(3*(n-1)+2,intfields,s);
438 iso->set_fields(3*(n-1) ,intfields,0);
439 iso->set_fields(3*(n-1)+1,intfields,2);
440 iso->set_fields(3*(n-1)+2,intfields,r);
450 returnval.push_back(iso);
459 int nfields =
m_f->m_fieldPts->GetNFields() +
m_f->m_fieldPts->GetDim();
468 for(
int i =0; i < iso.size(); ++i)
470 npts += iso[i]->get_nvert();
479 for(
int i =0; i < iso.size(); ++i)
481 for(
int j = 0; j < iso[i]->get_nvert(); ++j,++cnt)
483 newfields[0][cnt] = iso[i]->get_x(j);
484 newfields[1][cnt] = iso[i]->get_y(j);
485 newfields[2][cnt] = iso[i]->get_z(j);
491 for(
int f = 0; f < nfields-3; ++f)
496 for(
int i =0; i < iso.size(); ++i)
498 for(
int j = 0; j < iso[i]->get_nvert(); ++j,++cnt)
500 newfields[f+3][cnt] = iso[i]->get_fields(f,j);
505 m_f->m_fieldPts->SetPts(newfields);
508 vector<Array<OneD, int> > ptsConn;
509 m_f->m_fieldPts->GetConnectivity(ptsConn);
512 for(
int i =0; i < iso.size(); ++i)
514 int ntris = iso[i]->get_ntris();
517 for(
int j = 0; j < 3*ntris; ++j)
519 conn[j] = cnt + iso[i]->get_vid(j);
521 ptsConn.push_back(conn);
522 cnt += iso[i]->get_nvert();
524 m_f->m_fieldPts->SetConnectivity(ptsConn);
529 register int i,j,cnt;
531 vector<IsoVertex> vert;
545 for(cnt =0, i = 0; i < 3; ++i)
550 for(
int f = 0; f <
m_fields.size(); ++f)
562 for(j = 0; j < 3; ++j)
568 pt =
find(vert.begin(),vert.end(),v);
571 m_vid[3*i+j] = pt[0].m_id;
577 for(
int f = 0; f <
m_fields.size(); ++f)
598 for(j = 3*i; j < 3*(m_ntris-1); ++j)
616 for(
int f = 0; f <
m_fields.size(); ++f)
623 m_x[i] = vert[i].m_x;
624 m_y[i] = vert[i].m_y;
625 m_z[i] = vert[i].m_z;
626 for(
int f = 0; f <
m_fields.size(); ++f)
628 m_fields[f][i] = vert[i].m_fields[f];
654 if((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2) < SQ_PNT_TOL)
676 for(i = 0; i < niso; ++i)
680 m_ntris += iso[i]->m_ntris;
687 for(i = 0; i < niso; ++i)
691 m_nvert += iso[i]->m_nvert;
695 vector< vector<int> > isocon;
702 vector<Array<OneD, NekDouble> > sph(niso);
704 for(i = 0; i < niso; ++i)
709 rng[0] = rng[3] = iso[i]->m_x[0];
710 rng[1] = rng[4] = iso[i]->m_x[1];
711 rng[2] = rng[5] = iso[i]->m_x[2];
713 for(id1 = 1; id1 < iso[i]->m_nvert;++id1)
715 rng[0] = min(rng[0],iso[i]->
m_x[i]);
716 rng[1] = min(rng[1],iso[i]->
m_y[i]);
717 rng[2] = min(rng[2],iso[i]->
m_z[i]);
719 rng[3] = max(rng[3],iso[i]->
m_x[i]);
720 rng[4] = max(rng[4],iso[i]->
m_y[i]);
721 rng[5] = max(rng[5],iso[i]->
m_z[i]);
725 sph[i][0] = (rng[3]+rng[0])/2.0;
726 sph[i][1] = (rng[4]+rng[1])/2.0;
727 sph[i][2] = (rng[5]+rng[2])/2.0;
730 sph[i][3] = sqrt((rng[3]-rng[0])*(rng[3]-rng[0]) +
731 (rng[4]-rng[1])*(rng[4]-rng[1]) +
732 (rng[5]-rng[2])*(rng[5]-rng[2]));
735 for(i = 0; i < niso; ++i)
737 for(j = i+1; j < niso; ++j)
739 NekDouble diff=sqrt((sph[i][0]-sph[j][0])*(sph[i][0]-sph[j][0])+
740 (sph[i][1]-sph[j][1])*(sph[i][1]-sph[j][1])+
741 (sph[i][2]-sph[j][2])*(sph[i][2]-sph[j][2]));
744 if(diff < sph[i][3] + sph[j][3])
746 isocon[i].push_back(j);
753 for(i = 0; i < niso; ++i)
759 cout <<
"GlobalCondense: Matching Vertices [" << endl << flush;
763 for(i = 0; i < niso; ++i)
765 for(n = 0; n < isocon[i].size(); ++n)
767 int con = isocon[i][n];
768 totpts += iso[i]->m_nvert*iso[con]->m_nvert;
771 int totchk = totpts/50;
773 for(i = 0; i < niso; ++i)
775 for(n = 0; n < isocon[i].size(); ++n)
777 int con = isocon[i][n];
778 for(id1 = 0; id1 < iso[i]->m_nvert; ++id1)
780 for(id2 = 0; id2 < iso[con]->m_nvert; ++id2, ++cnt)
784 cout <<cnt_out <<
"%" <<
'\r' << flush;
788 if((vidmap[con][id2] == -1)||(vidmap[i][id1] == -1))
791 iso[i]->
m_z[id1], iso[con]->
m_x[id2],
792 iso[con]->
m_y[id2],iso[con]->
m_z[id2]))
794 if((vidmap[i][id1] == -1) &&
795 (vidmap[con][id2] != -1))
797 vidmap[i][id1] = vidmap[con][id2];
799 else if((vidmap[con][id2] == -1) &&
800 (vidmap[i][id1] != -1))
802 vidmap[con][id2] = vidmap[i][id1];
804 else if((vidmap[con][id2] == -1) &&
805 (vidmap[i][id1] == -1))
807 vidmap[i][id1] = vidmap[con][id2] = nvert++;
815 for(id1 = 0; id1 < iso[i]->m_nvert;++id1)
817 if(vidmap[i][id1] == -1)
819 vidmap[i][id1] = nvert++;
823 cout <<endl <<
"]"<<endl;
828 for(n = 0; n < niso; ++n)
830 for(i = 0; i < iso[n]->m_ntris; ++i,nelmt++)
834 m_vid[3*nelmt+j] = vidmap[n][iso[n]->m_vid[3*i+j]];
846 for(i = 0; i < iso[0]->m_fields.size(); ++i)
853 for(n = 0; n < niso; ++n)
855 for(i = 0; i < iso[n]->m_nvert; ++i)
857 m_x[vidmap[n][i]] = iso[n]->m_x[i];
858 m_y[vidmap[n][i]] = iso[n]->m_y[i];
859 m_z[vidmap[n][i]] = iso[n]->m_z[i];
861 for(j = 0; j <
m_fields.size(); ++j)
863 m_fields[j][vidmap[n][i]] = iso[n]->m_fields[j][i];
875 vector< vector<int> > adj,vertcon;
883 for(j = 0; j < 3; ++j)
885 vertcon[
m_vid[3*i+j]].push_back(i);
894 for(ipt = vertcon[i].begin(); ipt != vertcon[i].end(); ++ipt)
896 for(j = 0; j < 3; ++j)
899 if(
m_vid[3*(*ipt)+j] != i)
902 for(iad = adj[i].begin(); iad != adj[i].end();++iad)
904 if(*iad == (
m_vid[3*(*ipt)+j]))
break;
907 if(iad == adj[i].end())
909 adj[i].push_back(
m_vid[3*(*ipt)+j]);
921 for (iter=0;iter<n_iter;iter++)
928 del_v[0] = del_v[1] = del_v[2] = 0.0;
930 for(iad = adj[i].begin(); iad != adj[i].end(); ++iad)
932 del_v[0] = del_v[0] + (
m_x[*iad]-
m_x[i])*w;
933 del_v[1] = del_v[1] + (
m_y[*iad]-
m_y[i])*w;
934 del_v[2] = del_v[2] + (
m_z[*iad]-
m_z[i])*w;
937 xtemp[i] =
m_x[i] + del_v[0] * lambda;
938 ytemp[i] =
m_y[i] + del_v[1] * lambda;
939 ztemp[i] =
m_z[i] + del_v[2] * lambda;
947 del_v[0] = del_v[1] = del_v[2] = 0;
949 for(iad = adj[i].begin(); iad != adj[i].end(); ++iad)
951 del_v[0] = del_v[0] + (
m_x[*iad]-
m_x[i])*w;
952 del_v[1] = del_v[1] + (
m_y[*iad]-
m_y[i])*w;
953 del_v[2] = del_v[2] + (
m_z[*iad]-
m_z[i])*w;
956 m_x[i] = xtemp[i] + del_v[0] * mu;
957 m_y[i] = ytemp[i] + del_v[1] * mu;
958 m_z[i] = ztemp[i] + del_v[2] * mu;
977 for(j = 0; j < 3; ++j)
979 vertcon[
m_vid[3*i+j]].push_back(i);
987 cout <<
"Identifying separate regions [." << flush ;
991 if(vidregion[k] == -1)
993 vidregion[k] = ++nregions;
996 for(ipt = vertcon[k].begin(); ipt != vertcon[k].end(); ++ipt)
998 for(i = 0; i < 3; ++i)
1000 if(vidregion[
id =
m_vid[3*(ipt[0])+i]] == -1)
1002 tocheck.push_back(
id);
1003 vidregion[id] = nregions;
1010 while(tocheck.size())
1012 cid = tocheck.begin();
1013 while(cid != tocheck.end())
1017 for(ipt = vertcon[*cid].begin(); ipt != vertcon[*cid].end(); ++ipt)
1019 for(i = 0; i < 3; ++i)
1021 if(vidregion[
id =
m_vid[3*(ipt[0])+i]] == -1)
1023 tocheck.push_back(
id);
1024 vidregion[id] = nregions;
1030 tocheck.pop_front();
1038 cout <<
"]" << endl << flush ;
1046 nvert[vidregion[i]] +=1;
1052 nelmt[vidregion[
m_vid[3*i]]] +=1;
1057 for(
int n = 0; n < nregions; ++n)
1059 if(nelmt[n] > minsize)
1064 iso->m_ntris = nelmt[n];
1067 iso->m_nvert = nvert[n];
1068 iso->m_x.resize(nvert[n]);
1069 iso->m_y.resize(nvert[n]);
1070 iso->m_z.resize(nvert[n]);
1072 iso->m_fields.resize(nfields);
1073 for(i = 0; i < nfields; ++i)
1075 iso->m_fields[i].resize(nvert[n]);
1084 if(vidregion[i] == n)
1093 if(vidregion[
m_vid[3*i]] == n)
1095 for(j = 0; j < 3; ++j)
1097 iso->m_vid[3*cnt+j] = vidmap[
m_vid[3*i+j]];
1099 iso->m_x[vidmap[m_vid[3*i+j]]] =
m_x[m_vid[3*i+j]];
1100 iso->m_y[vidmap[m_vid[3*i+j]]] =
m_y[m_vid[3*i+j]];
1101 iso->m_z[vidmap[m_vid[3*i+j]]] =
m_z[m_vid[3*i+j]];
1103 for(k = 0; k < nfields; ++k)
1105 iso->m_fields[k][vidmap[m_vid[3*i+j]]] =
m_fields[k][m_vid[3*i+j]];
1112 WARNINGL0(cnt == nelmt[n],
"Number of elements do not match");
1113 sep_iso.push_back(iso);
#define ASSERTL0(condition, msg)
pair< ModuleType, string > ModuleKey
static boost::shared_ptr< DataType > AllocateSharedPtr()
Allocate a shared pointer from the memory pool.
void SetupEquiSpacedField(void)
virtual ~ProcessIsoContour()
map< string, ConfigOption > m_config
List of configuration values.
void globalcondense(vector< boost::shared_ptr< Iso > > &iso)
FieldSharedPtr m_f
Field object.
vector< NekDouble > m_fields
void smooth(int n_iter, NekDouble lambda, NekDouble mu)
boost::shared_ptr< Iso > IsoSharedPtr
#define WARNINGL0(condition, msg)
bool operator!=(const IsoVertex &x, const IsoVertex &y)
void separate_regions(vector< boost::shared_ptr< Iso > > &iso, int minsize)
void TwoPairs(Array< OneD, NekDouble > &cx, Array< OneD, NekDouble > &cy, Array< OneD, NekDouble > &cz, int &pr)
boost::shared_ptr< Field > FieldSharedPtr
vector< vector< NekDouble > > m_fields
This class defines evaluator of analytic (symbolic) mathematical expressions. Expressions are allowed...
Represents a command-line configuration option.
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
bool operator==(TriFaceIDs const &p1, TriFaceIDs const &p2)
vector< IsoSharedPtr > ExtractContour(const int fieldid, const NekDouble val)
InputIterator find(InputIterator first, InputIterator last, InputIterator startingpoint, const EqualityComparable &value)
void ResetFieldPts(vector< IsoSharedPtr > &iso)
bool same(NekDouble x1, NekDouble y1, NekDouble z1, NekDouble x2, NekDouble y2, NekDouble z2)
void ThreeSimilar(const int i, const int j, const int k, int &pr, int &ps)
void Zero(int n, T *x, const int incx)
Zero vector.
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
This processing module interpolates one field to another.
ModuleFactory & GetModuleFactory()
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, tDescription pDesc="")
Register a class with the factory.