10 #ifndef MUELU_VISUALIZATIONHELPERS_DEF_HPP_
11 #define MUELU_VISUALIZATIONHELPERS_DEF_HPP_
14 #include <Xpetra_CrsMatrixWrap.hpp>
16 #include <Xpetra_MultiVectorFactory.hpp>
27 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
31 validParamList->
set<std::string>(
"visualization: output filename",
"viz%LEVELID",
"filename for VTK-style visualization output");
32 validParamList->
set<
int>(
"visualization: output file: time step", 0,
"time step variable for output file name");
33 validParamList->
set<
int>(
"visualization: output file: iter", 0,
"nonlinear iteration variable for output file name");
34 validParamList->
set<std::string>(
"visualization: style",
"Point Cloud",
"style of aggregate visualization for VTK output. Can be 'Point Cloud', 'Jacks', 'Convex Hulls'");
35 validParamList->
set<
bool>(
"visualization: build colormap",
false,
"Whether to build a random color map in a separate xml file.");
36 validParamList->
set<
bool>(
"visualization: fine graph edges",
false,
"Whether to draw all fine node connections along with the aggregates.");
38 return validParamList;
41 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
43 vertices.reserve(numFineNodes);
44 geomSizes.reserve(numFineNodes);
46 vertices.push_back(i);
47 geomSizes.push_back(1);
51 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
55 vertices.reserve(vertices.size() + 3 * (numFineNodes - numLocalAggs));
56 geomSizes.reserve(vertices.size() + 2 * (numFineNodes - numLocalAggs));
58 for (
int i = 0; i < numLocalAggs; i++)
62 int numInAggFound = 0;
63 for (
int j = 0; j < numFineNodes; j++) {
69 if (vertex2AggId[root] == vertex2AggId[j]) {
70 vertices.push_back(root);
71 vertices.push_back(j);
72 geomSizes.push_back(2);
74 vertices.push_back(j);
75 geomSizes.push_back(1);
85 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
86 void VisualizationHelpers<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doConvexHulls2D(std::vector<int>& vertices, std::vector<int>& geomSizes,
LO numLocalAggs,
LO numFineNodes,
const std::vector<bool>& ,
const ArrayRCP<LO>& vertex2AggId,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& xCoords,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& yCoords) {
89 for (
int agg = 0; agg < numLocalAggs; agg++) {
90 std::vector<int> aggNodes;
91 for (
int i = 0; i < numFineNodes; i++) {
92 if (vertex2AggId[i] == agg)
93 aggNodes.push_back(i);
98 "CoarseningVisualization::doConvexHulls2D: aggregate contains zero nodes!");
99 if (aggNodes.size() == 1) {
100 vertices.push_back(aggNodes.front());
101 geomSizes.push_back(1);
104 if (aggNodes.size() == 2) {
105 vertices.push_back(aggNodes.front());
106 vertices.push_back(aggNodes.back());
107 geomSizes.push_back(2);
110 int N = (int)aggNodes.size();
111 using MyPair = std::pair<myVec2, int>;
112 std::vector<MyPair> pointsAndIndex(N);
113 for (
int i = 0; i < N; i++) {
114 pointsAndIndex[i] = std::make_pair(
myVec2(xCoords[aggNodes[i]], yCoords[aggNodes[i]]), i);
118 std::sort(pointsAndIndex.begin(), pointsAndIndex.end(), [](
const MyPair& a,
const MyPair& b) {
119 return a.first.x < b.first.x || (a.first.x == b.first.x && a.first.y < b.first.y);
123 bool colinear =
true;
124 for (
int i = 0; i < N; i++) {
125 if (ccw(pointsAndIndex[i].first, pointsAndIndex[(i + 1) % N].first, pointsAndIndex[(i + 2) % N].first) != 0) {
132 vertices.push_back(aggNodes[pointsAndIndex.front().second]);
133 vertices.push_back(aggNodes[pointsAndIndex.back().second]);
134 geomSizes.push_back(2);
136 std::vector<int> hull(2 * N);
140 for (
int i = 0; i < N; i++) {
141 while (count >= 2 && ccw(pointsAndIndex[hull[count - 2]].first, pointsAndIndex[hull[count - 1]].first, pointsAndIndex[i].first) <= 0) {
149 for (
int i = N - 1; i > 0; i--) {
150 while (count >= t && ccw(pointsAndIndex[hull[count - 2]].first, pointsAndIndex[hull[count - 1]].first, pointsAndIndex[i - 1].first) <= 0) {
153 hull[count++] = i - 1;
157 hull.resize(count - 1);
160 for (
int i = 0; i < (int)hull.size(); i++) {
161 TEUCHOS_TEST_FOR_EXCEPTION(ccw(pointsAndIndex[hull[i]].first, pointsAndIndex[hull[(i + 1) % hull.size()]].first, pointsAndIndex[hull[(i + 1) % hull.size()]].first) == 1,
Exceptions::RuntimeError,
"CoarseningVisualization::doConvexHulls2D: counter-clockwise verification fails");
165 for (
int i = 0; i < (int)hull.size(); i++) {
166 hull[i] = aggNodes[pointsAndIndex[hull[i]].second];
169 vertices.reserve(vertices.size() + hull.size());
170 for (
size_t i = 0; i < hull.size(); i++) {
171 vertices.push_back(hull[i]);
173 geomSizes.push_back(hull.size());
179 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
180 void VisualizationHelpers<Scalar, LocalOrdinal, GlobalOrdinal, Node>::doConvexHulls3D(std::vector<int>& vertices, std::vector<int>& geomSizes,
LO numLocalAggs,
LO numFineNodes,
const std::vector<bool>& ,
const ArrayRCP<LO>& vertex2AggId,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& xCoords,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& yCoords,
const Teuchos::ArrayRCP<
const typename Teuchos::ScalarTraits<Scalar>::coordinateType>& zCoords) {
185 typedef std::list<int>::iterator Iter;
186 for (
int agg = 0; agg < numLocalAggs; agg++) {
187 std::list<int> aggNodes;
188 for (
int i = 0; i < numFineNodes; i++) {
189 if (vertex2AggId[i] == agg)
190 aggNodes.push_back(i);
194 "CoarseningVisualization::doConvexHulls3D: aggregate contains zero nodes!");
195 if (aggNodes.size() == 1) {
196 vertices.push_back(aggNodes.front());
197 geomSizes.push_back(1);
199 }
else if (aggNodes.size() == 2) {
200 vertices.push_back(aggNodes.front());
201 vertices.push_back(aggNodes.back());
202 geomSizes.push_back(2);
206 bool areCollinear =
true;
208 Iter it = aggNodes.begin();
209 myVec3 firstVec(xCoords[*it], yCoords[*it], zCoords[*it]);
213 myVec3 secondVec(xCoords[*it], yCoords[*it], zCoords[*it]);
214 comp = vecSubtract(secondVec, firstVec);
217 for (; it != aggNodes.end(); it++) {
218 myVec3 thisVec(xCoords[*it], yCoords[*it], zCoords[*it]);
219 myVec3 cross = crossProduct(vecSubtract(thisVec, firstVec), comp);
220 if (mymagnitude(cross) > 1e-10) {
221 areCollinear =
false;
229 Iter min = aggNodes.begin();
230 Iter max = aggNodes.begin();
231 Iter it = ++aggNodes.begin();
232 for (; it != aggNodes.end(); it++) {
233 if (xCoords[*it] < xCoords[*min])
235 else if (xCoords[*it] == xCoords[*min]) {
236 if (yCoords[*it] < yCoords[*min])
238 else if (yCoords[*it] == yCoords[*min]) {
239 if (zCoords[*it] < zCoords[*min]) min = it;
242 if (xCoords[*it] > xCoords[*max])
244 else if (xCoords[*it] == xCoords[*max]) {
245 if (yCoords[*it] > yCoords[*max])
247 else if (yCoords[*it] == yCoords[*max]) {
248 if (zCoords[*it] > zCoords[*max])
253 vertices.push_back(*min);
254 vertices.push_back(*max);
255 geomSizes.push_back(2);
258 bool areCoplanar =
true;
261 Iter vert = aggNodes.begin();
262 myVec3 v1(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
264 myVec3 v2(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
266 myVec3 v3(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
269 while (mymagnitude(crossProduct(vecSubtract(v1, v2), vecSubtract(v1, v3))) < 1e-10) {
271 v3 =
myVec3(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
274 for (; vert != aggNodes.end(); vert++) {
275 myVec3 pt(xCoords[*vert], yCoords[*vert], zCoords[*vert]);
276 if (fabs(pointDistFromTri(pt, v1, v2, v3)) > 1e-12) {
283 myVec3 planeNorm = getNorm(v1, v2, v3);
284 planeNorm.
x = fabs(planeNorm.
x);
285 planeNorm.
y = fabs(planeNorm.
y);
286 planeNorm.
z = fabs(planeNorm.
z);
287 std::vector<myVec2> points;
288 std::vector<int> nodes;
289 if (planeNorm.
x >= planeNorm.
y && planeNorm.
x >= planeNorm.
z) {
291 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
292 nodes.push_back(*it);
293 points.push_back(
myVec2(yCoords[*it], zCoords[*it]));
296 if (planeNorm.
y >= planeNorm.
x && planeNorm.
y >= planeNorm.
z) {
298 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
299 nodes.push_back(*it);
300 points.push_back(
myVec2(xCoords[*it], zCoords[*it]));
303 if (planeNorm.
z >= planeNorm.
x && planeNorm.
z >= planeNorm.
y) {
304 for (Iter it = aggNodes.begin(); it != aggNodes.end(); it++) {
305 nodes.push_back(*it);
306 points.push_back(
myVec2(xCoords[*it], yCoords[*it]));
309 std::vector<int> convhull2d = giftWrap(points, nodes, xCoords, yCoords);
310 geomSizes.push_back(convhull2d.size());
311 vertices.reserve(vertices.size() + convhull2d.size());
312 for (
size_t i = 0; i < convhull2d.size(); i++)
313 vertices.push_back(convhull2d[i]);
317 Iter exIt = aggNodes.begin();
318 int extremeSix[] = {*exIt, *exIt, *exIt, *exIt, *exIt, *exIt};
320 for (; exIt != aggNodes.end(); exIt++) {
322 if (xCoords[*it] < xCoords[extremeSix[0]] ||
323 (xCoords[*it] == xCoords[extremeSix[0]] && yCoords[*it] < yCoords[extremeSix[0]]) ||
324 (xCoords[*it] == xCoords[extremeSix[0]] && yCoords[*it] == yCoords[extremeSix[0]] && zCoords[*it] < zCoords[extremeSix[0]]))
326 if (xCoords[*it] > xCoords[extremeSix[1]] ||
327 (xCoords[*it] == xCoords[extremeSix[1]] && yCoords[*it] > yCoords[extremeSix[1]]) ||
328 (xCoords[*it] == xCoords[extremeSix[1]] && yCoords[*it] == yCoords[extremeSix[1]] && zCoords[*it] > zCoords[extremeSix[1]]))
330 if (yCoords[*it] < yCoords[extremeSix[2]] ||
331 (yCoords[*it] == yCoords[extremeSix[2]] && zCoords[*it] < zCoords[extremeSix[2]]) ||
332 (yCoords[*it] == yCoords[extremeSix[2]] && zCoords[*it] == zCoords[extremeSix[2]] && xCoords[*it] < xCoords[extremeSix[2]]))
334 if (yCoords[*it] > yCoords[extremeSix[3]] ||
335 (yCoords[*it] == yCoords[extremeSix[3]] && zCoords[*it] > zCoords[extremeSix[3]]) ||
336 (yCoords[*it] == yCoords[extremeSix[3]] && zCoords[*it] == zCoords[extremeSix[3]] && xCoords[*it] > xCoords[extremeSix[3]]))
338 if (zCoords[*it] < zCoords[extremeSix[4]] ||
339 (zCoords[*it] == zCoords[extremeSix[4]] && xCoords[*it] < xCoords[extremeSix[4]]) ||
340 (zCoords[*it] == zCoords[extremeSix[4]] && xCoords[*it] == xCoords[extremeSix[4]] && yCoords[*it] < yCoords[extremeSix[4]]))
342 if (zCoords[*it] > zCoords[extremeSix[5]] ||
343 (zCoords[*it] == zCoords[extremeSix[5]] && xCoords[*it] > xCoords[extremeSix[5]]) ||
344 (zCoords[*it] == zCoords[extremeSix[5]] && xCoords[*it] == xCoords[extremeSix[5]] && yCoords[*it] > zCoords[extremeSix[5]]))
348 for (
int i = 0; i < 6; i++) {
349 myVec3 thisExtremeVec(xCoords[extremeSix[i]], yCoords[extremeSix[i]], zCoords[extremeSix[i]]);
350 extremeVectors[i] = thisExtremeVec;
355 for (
int i = 0; i < 5; i++) {
356 for (
int j = i + 1; j < 6; j++) {
357 double thisDist = distance(extremeVectors[i], extremeVectors[j]);
359 if (thisDist > maxDist && thisDist - maxDist > 1e-12) {
366 std::list<myTriangle> hullBuilding;
368 aggNodes.remove(extremeSix[base1]);
369 aggNodes.remove(extremeSix[base2]);
372 tri.
v1 = extremeSix[base1];
373 tri.
v2 = extremeSix[base2];
377 myVec3 b1 = extremeVectors[base1];
378 myVec3 b2 = extremeVectors[base2];
380 for (Iter node = aggNodes.begin(); node != aggNodes.end(); node++) {
381 myVec3 nodePos(xCoords[*node], yCoords[*node], zCoords[*node]);
382 double dist = mymagnitude(crossProduct(vecSubtract(nodePos, b1), vecSubtract(nodePos, b2))) / mymagnitude(vecSubtract(b2, b1));
384 if (dist > maxDist && dist - maxDist > 1e-12) {
391 hullBuilding.push_back(tri);
392 myVec3 b3(xCoords[*thirdNode], yCoords[*thirdNode], zCoords[*thirdNode]);
393 aggNodes.erase(thirdNode);
396 int fourthVertex = -1;
397 for (Iter node = aggNodes.begin(); node != aggNodes.end(); node++) {
398 myVec3 thisNode(xCoords[*node], yCoords[*node], zCoords[*node]);
399 double nodeDist = pointDistFromTri(thisNode, b1, b2, b3);
401 if (nodeDist > maxDist && nodeDist - maxDist > 1e-12) {
403 fourthVertex = *node;
406 aggNodes.remove(fourthVertex);
407 myVec3 b4(xCoords[fourthVertex], yCoords[fourthVertex], zCoords[fourthVertex]);
410 tri = hullBuilding.front();
411 tri.
v1 = fourthVertex;
412 hullBuilding.push_back(tri);
413 tri = hullBuilding.front();
414 tri.
v2 = fourthVertex;
415 hullBuilding.push_back(tri);
416 tri = hullBuilding.front();
417 tri.
v3 = fourthVertex;
418 hullBuilding.push_back(tri);
420 myVec3 barycenter((b1.
x + b2.
x + b3.
x + b4.
x) / 4.0, (b1.
y + b2.
y + b3.
y + b4.
y) / 4.0, (b1.
z + b2.
z + b3.
z + b4.
z) / 4.0);
421 for (std::list<myTriangle>::iterator tetTri = hullBuilding.begin(); tetTri != hullBuilding.end(); tetTri++) {
422 myVec3 triVert1(xCoords[tetTri->v1], yCoords[tetTri->v1], zCoords[tetTri->v1]);
423 myVec3 triVert2(xCoords[tetTri->v2], yCoords[tetTri->v2], zCoords[tetTri->v2]);
424 myVec3 triVert3(xCoords[tetTri->v3], yCoords[tetTri->v3], zCoords[tetTri->v3]);
425 myVec3 trinorm = getNorm(triVert1, triVert2, triVert3);
426 myVec3 ptInPlane = tetTri == hullBuilding.begin() ? b1 : b4;
427 if (isInFront(barycenter, ptInPlane, trinorm)) {
430 int temp = tetTri->v1;
431 tetTri->v1 = tetTri->v2;
443 for (std::list<myTriangle>::iterator tetTri = hullBuilding.begin(); tetTri != hullBuilding.end(); tetTri++) {
444 myVec3 triVert1(xCoords[tetTri->v1], yCoords[tetTri->v1], zCoords[tetTri->v1]);
445 myVec3 triVert2(xCoords[tetTri->v2], yCoords[tetTri->v2], zCoords[tetTri->v2]);
446 myVec3 triVert3(xCoords[tetTri->v3], yCoords[tetTri->v3], zCoords[tetTri->v3]);
447 trinorms[index] = getNorm(triVert1, triVert2, triVert3);
450 std::list<int> startPoints1;
451 std::list<int> startPoints2;
452 std::list<int> startPoints3;
453 std::list<int> startPoints4;
456 Iter point = aggNodes.begin();
457 while (!aggNodes.empty())
459 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
462 if (isInFront(pointVec, b1, trinorms[0])) {
463 startPoints1.push_back(*point);
464 point = aggNodes.erase(point);
465 }
else if (isInFront(pointVec, b4, trinorms[1])) {
466 startPoints2.push_back(*point);
467 point = aggNodes.erase(point);
468 }
else if (isInFront(pointVec, b4, trinorms[2])) {
469 startPoints3.push_back(*point);
470 point = aggNodes.erase(point);
471 }
else if (isInFront(pointVec, b4, trinorms[3])) {
472 startPoints4.push_back(*point);
473 point = aggNodes.erase(point);
475 point = aggNodes.erase(point);
480 typedef std::list<myTriangle>::iterator TriIter;
481 TriIter firstTri = hullBuilding.begin();
490 if (!startPoints1.empty())
491 processTriangle(hullBuilding, start1, startPoints1, barycenter, xCoords, yCoords, zCoords);
492 if (!startPoints2.empty())
493 processTriangle(hullBuilding, start2, startPoints2, barycenter, xCoords, yCoords, zCoords);
494 if (!startPoints3.empty())
495 processTriangle(hullBuilding, start3, startPoints3, barycenter, xCoords, yCoords, zCoords);
496 if (!startPoints4.empty())
497 processTriangle(hullBuilding, start4, startPoints4, barycenter, xCoords, yCoords, zCoords);
500 vertices.reserve(vertices.size() + 3 * hullBuilding.size());
501 for (TriIter hullTri = hullBuilding.begin(); hullTri != hullBuilding.end(); hullTri++) {
502 vertices.push_back(hullTri->v1);
503 vertices.push_back(hullTri->v2);
504 vertices.push_back(hullTri->v3);
505 geomSizes.push_back(3);
510 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
514 std::vector<std::pair<int, int> > vert1;
520 for (
int gEdge = 0; gEdge < int(neighbors.length); ++gEdge) {
521 vert1.push_back(std::pair<int, int>(locRow, neighbors(gEdge)));
524 for (
size_t i = 0; i < vert1.size(); i++) {
525 if (vert1[i].first > vert1[i].second) {
526 int temp = vert1[i].first;
527 vert1[i].first = vert1[i].second;
528 vert1[i].second = temp;
531 std::sort(vert1.begin(), vert1.end());
532 std::vector<std::pair<int, int> >::iterator newEnd = unique(vert1.begin(), vert1.end());
533 vert1.erase(newEnd, vert1.end());
535 vertices.reserve(2 * vert1.size());
536 geomSizes.reserve(vert1.size());
537 for (
size_t i = 0; i < vert1.size(); i++) {
538 vertices.push_back(vert1[i].first);
539 vertices.push_back(vert1[i].second);
540 geomSizes.push_back(2);
544 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
546 const double ccw_zero_threshold = 1e-8;
547 double val = (b.
x - a.
x) * (c.
y - a.
y) - (b.
y - a.
y) * (c.
x - a.
x);
548 return (val > ccw_zero_threshold) ? 1 : ((val < -ccw_zero_threshold) ? -1 : 0);
551 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
553 return myVec3(v1.
y * v2.
z - v1.
z * v2.
y, v1.
z * v2.
x - v1.
x * v2.
z, v1.
x * v2.
y - v1.
y * v2.
x);
556 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
558 return v1.
x * v2.
x + v1.
y * v2.
y;
561 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
563 return v1.
x * v2.
x + v1.
y * v2.
y + v1.
z * v2.
z;
566 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
568 myVec3 rel(point.
x - inPlane.
x, point.
y - inPlane.
y, point.
z - inPlane.
z);
569 return dotProduct(rel, n) > 1e-12 ?
true :
false;
572 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
574 return sqrt(dotProduct(vec, vec));
577 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
579 return sqrt(dotProduct(vec, vec));
582 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
584 return mymagnitude(vecSubtract(p1, p2));
587 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
589 return mymagnitude(vecSubtract(p1, p2));
592 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
597 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
602 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
608 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
611 return crossProduct(vecSubtract(v2, v1), vecSubtract(v3, v1));
615 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
618 myVec3 norm = getNorm(v1, v2, v3);
620 double normScl = mymagnitude(norm);
622 if (normScl > 1e-8) {
626 rv = fabs(dotProduct(norm, vecSubtract(point, v1)));
629 myVec3 test1 = vecSubtract(v3, v1);
630 myVec3 test2 = vecSubtract(v2, v1);
631 bool useTest1 = mymagnitude(test1) > 0.0 ?
true :
false;
632 bool useTest2 = mymagnitude(test2) > 0.0 ?
true :
false;
633 if (useTest1 ==
true) {
634 double normScl1 = mymagnitude(test1);
638 rv = fabs(dotProduct(test1, vecSubtract(point, v1)));
639 }
else if (useTest2 ==
true) {
640 double normScl2 = mymagnitude(test2);
644 rv = fabs(dotProduct(test2, vecSubtract(point, v1)));
647 "VisualizationHelpers::pointDistFromTri: Could not determine the distance of a point to a triangle.");
653 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
659 typedef std::list<int>::iterator Iter;
660 typedef std::list<myTriangle>::iterator TriIter;
661 typedef list<pair<int, int> >::iterator EdgeIter;
664 myVec3 v1(xCoords[tri.
v1], yCoords[tri.
v1], zCoords[tri.
v1]);
665 myVec3 v2(xCoords[tri.
v2], yCoords[tri.
v2], zCoords[tri.
v2]);
666 myVec3 v3(xCoords[tri.
v3], yCoords[tri.
v3], zCoords[tri.
v3]);
668 Iter farPoint = pointsInFront.begin();
669 for (Iter point = pointsInFront.begin(); point != pointsInFront.end(); point++) {
670 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
671 double dist = pointDistFromTri(pointVec, v1, v2, v3);
673 if (dist > maxDist && dist - maxDist > 1e-12) {
675 farPointVec = pointVec;
681 vector<myTriangle> visible;
682 for (TriIter it = tris.begin(); it != tris.end();) {
683 myVec3 vec1(xCoords[it->v1], yCoords[it->v1], zCoords[it->v1]);
684 myVec3 vec2(xCoords[it->v2], yCoords[it->v2], zCoords[it->v2]);
685 myVec3 vec3(xCoords[it->v3], yCoords[it->v3], zCoords[it->v3]);
686 myVec3 norm = getNorm(vec1, vec2, vec3);
687 if (isInFront(farPointVec, vec1, norm)) {
688 visible.push_back(*it);
695 list<pair<int, int> > horizon;
698 for (vector<myTriangle>::iterator it = visible.begin(); it != visible.end(); it++) {
699 pair<int, int> e1(it->v1, it->v2);
700 pair<int, int> e2(it->v2, it->v3);
701 pair<int, int> e3(it->v1, it->v3);
703 if (e1.first > e1.second) {
705 e1.first = e1.second;
708 if (e2.first > e2.second) {
710 e2.first = e2.second;
713 if (e3.first > e3.second) {
715 e3.first = e3.second;
718 horizon.push_back(e1);
719 horizon.push_back(e2);
720 horizon.push_back(e3);
726 EdgeIter it = horizon.begin();
727 while (it != horizon.end()) {
728 int occur = count(horizon.begin(), horizon.end(), *it);
730 pair<int, int> removeVal = *it;
731 while (removeVal == *it && !(it == horizon.end()))
732 it = horizon.erase(it);
738 list<myTriangle> newTris;
739 for (EdgeIter it = horizon.begin(); it != horizon.end(); it++) {
740 myTriangle t(it->first, it->second, *farPoint);
741 newTris.push_back(t);
744 vector<myTriangle> trisToProcess;
745 vector<list<int> > newFrontPoints;
746 for (TriIter it = newTris.begin(); it != newTris.end(); it++) {
747 myVec3 t1(xCoords[it->v1], yCoords[it->v1], zCoords[it->v1]);
748 myVec3 t2(xCoords[it->v2], yCoords[it->v2], zCoords[it->v2]);
749 myVec3 t3(xCoords[it->v3], yCoords[it->v3], zCoords[it->v3]);
750 if (isInFront(barycenter, t1, getNorm(t1, t2, t3))) {
759 myVec3 outwardNorm = getNorm(t1, t2, t3);
762 trisToProcess.push_back(tris.back());
764 list<int> newInFront;
765 for (Iter point = pointsInFront.begin(); point != pointsInFront.end();) {
766 myVec3 pointVec(xCoords[*point], yCoords[*point], zCoords[*point]);
767 if (isInFront(pointVec, t1, outwardNorm)) {
768 newInFront.push_back(*point);
769 point = pointsInFront.erase(point);
773 newFrontPoints.push_back(newInFront);
775 vector<myTriangle> allRemoved;
776 for (
int i = 0; i < int(trisToProcess.size()); i++) {
777 if (!newFrontPoints[i].empty()) {
780 if (find(allRemoved.begin(), allRemoved.end(), trisToProcess[i]) == allRemoved.end() && !(trisToProcess[i] == tri)) {
781 vector<myTriangle> removedList = processTriangle(tris, trisToProcess[i], newFrontPoints[i], barycenter, xCoords, yCoords, zCoords);
782 for (
int j = 0; j < int(removedList.size()); j++)
783 allRemoved.push_back(removedList[j]);
790 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
793 "CoarseningVisualization::giftWrap: Gift wrap algorithm input has to have at least 3 points!");
795 #if 1 // TAW's version to determine "minimal" node
797 double min_x = points[0].x;
798 double min_y = points[0].y;
799 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
800 int i = it - nodes.begin();
801 if (points[i].x < min_x) min_x = points[i].x;
802 if (points[i].y < min_y) min_y = points[i].y;
807 myVec2 dummy_min(min_x, min_y);
810 std::vector<int> hull;
812 double mindist = distance(min, dummy_min);
813 std::vector<int>::iterator minNode = nodes.begin();
814 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
815 int i = it - nodes.begin();
816 if (distance(points[i], dummy_min) < mindist) {
817 mindist = distance(points[i], dummy_min);
822 hull.push_back(*minNode);
823 #else // Brian's code
824 std::vector<int> hull;
825 std::vector<int>::iterator minNode = nodes.begin();
827 for (std::vector<int>::iterator it = nodes.begin(); it != nodes.end(); it++) {
828 int i = it - nodes.begin();
829 if (points[i].x < min.
x || (fabs(points[i].x - min.
x) < 1e-10 && points[i].y < min.
y)) {
834 hull.push_back(*minNode);
837 bool includeMin =
false;
840 std::vector<int>::iterator leftMost = nodes.begin();
841 if (!includeMin && leftMost == minNode) {
844 std::vector<int>::iterator it = leftMost;
846 for (; it != nodes.end(); it++) {
847 if (it == minNode && !includeMin)
849 if (*it == hull.back())
853 myVec2 leftMostVec = points[leftMost - nodes.begin()];
854 myVec2 lastVec(xCoords[hull.back()], yCoords[hull.back()]);
855 myVec2 testNorm = getNorm(vecSubtract(leftMostVec, lastVec));
857 myVec2 itVec(xCoords[*it], yCoords[*it]);
858 double dotProd = dotProduct(testNorm, vecSubtract(itVec, lastVec));
859 if (-1e-8 < dotProd && dotProd < 1e-8) {
862 myVec2 itDist = vecSubtract(itVec, lastVec);
863 myVec2 leftMostDist = vecSubtract(leftMostVec, lastVec);
864 if (fabs(itDist.
x) + fabs(itDist.
y) > fabs(leftMostDist.
x) + fabs(leftMostDist.
y)) {
867 }
else if (dotProd > 0) {
872 if (*leftMost == *minNode)
874 hull.push_back(*leftMost);
882 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
885 vector<int> uniqueNodes = vertices;
886 sort(uniqueNodes.begin(), uniqueNodes.end());
887 vector<int>::iterator newUniqueFineEnd = unique(uniqueNodes.begin(), uniqueNodes.end());
888 uniqueNodes.erase(newUniqueFineEnd, uniqueNodes.end());
891 for (
int i = 0; i < int(vertices.size()); i++) {
893 int hi = uniqueNodes.size() - 1;
895 int search = vertices[i];
897 mid = lo + (hi - lo) / 2;
898 if (uniqueNodes[mid] == search)
900 else if (uniqueNodes[mid] > search)
905 if (uniqueNodes[mid] != search)
906 throw runtime_error(
"Issue in makeUnique_() - a point wasn't found in list.");
912 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
915 const int pos = result.find(replaceWhat);
918 result.replace(pos, replaceWhat.size(), replaceWithWhat);
923 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
925 std::string filenameToWrite = getBaseFileName(numProcs, level, pL);
927 return filenameToWrite;
930 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
932 std::string filenameToWrite = pL.
get<std::string>(
"visualization: output filename");
933 int timeStep = pL.
get<
int>(
"visualization: output file: time step");
934 int iter = pL.
get<
int>(
"visualization: output file: iter");
936 if (filenameToWrite.rfind(
".vtu") == std::string::npos)
937 filenameToWrite.append(
".vtu");
938 if (numProcs > 1 && filenameToWrite.rfind(
"%PROCID") == std::string::npos)
939 filenameToWrite.insert(filenameToWrite.rfind(
".vtu"),
"-proc%PROCID");
944 return filenameToWrite;
947 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
949 std::string filenameToWrite = getBaseFileName(numProcs, level, pL);
950 std::string masterStem = filenameToWrite.substr(0, filenameToWrite.rfind(
".vtu"));
951 masterStem = this->
replaceAll(masterStem,
"%PROCID",
"");
952 std::string pvtuFilename = masterStem +
"-master.pvtu";
956 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
958 std::string styleName =
"PointCloud";
960 std::string indent =
" ";
961 fout <<
"<!--" << styleName <<
" Aggregates Visualization-->" << std::endl;
962 fout <<
"<VTKFile type=\"UnstructuredGrid\" byte_order=\"LittleEndian\">" << std::endl;
963 fout <<
" <UnstructuredGrid>" << std::endl;
964 fout <<
" <Piece NumberOfPoints=\"" << uniqueFine.size() <<
"\" NumberOfCells=\"" << geomSizesFine.size() <<
"\">" << std::endl;
965 fout <<
" <PointData Scalars=\"Node Aggregate Processor\">" << std::endl;
968 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
970 std::string indent =
" ";
971 fout <<
" <DataArray type=\"Int32\" Name=\"Node\" format=\"ascii\">" << std::endl;
974 for (
size_t i = 0; i < uniqueFine.size(); i++) {
976 fout << uniqueFine[i] <<
" ";
978 fout << nodeMap->getGlobalElement(uniqueFine[i]) <<
" ";
984 fout <<
" </DataArray>" << std::endl;
987 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
989 std::string indent =
" ";
990 fout <<
" <DataArray type=\"Int32\" Name=\"Aggregate\" format=\"ascii\">" << std::endl;
992 for (
int i = 0; i < int(uniqueFine.size()); i++) {
993 fout << myAggOffset + vertex2AggId[uniqueFine[i]] <<
" ";
999 fout <<
" </DataArray>" << std::endl;
1000 fout <<
" <DataArray type=\"Int32\" Name=\"Processor\" format=\"ascii\">" << std::endl;
1002 for (
int i = 0; i < int(uniqueFine.size()); i++) {
1003 fout << myRank <<
" ";
1009 fout <<
" </DataArray>" << std::endl;
1010 fout <<
" </PointData>" << std::endl;
1013 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1015 std::string indent =
" ";
1016 fout <<
" <Points>" << std::endl;
1017 fout <<
" <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;
1019 for (
int i = 0; i < int(uniqueFine.size()); i++) {
1020 fout << fx[uniqueFine[i]] <<
" " << fy[uniqueFine[i]] <<
" ";
1024 fout << fz[uniqueFine[i]] <<
" ";
1030 fout <<
" </DataArray>" << std::endl;
1031 fout <<
" </Points>" << std::endl;
1034 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1036 std::string indent =
" ";
1037 fout <<
" <Cells>" << std::endl;
1038 fout <<
" <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">" << std::endl;
1040 for (
int i = 0; i < int(vertices.size()); i++) {
1041 fout << vertices[i] <<
" ";
1047 fout <<
" </DataArray>" << std::endl;
1048 fout <<
" <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">" << std::endl;
1051 for (
int i = 0; i < int(geomSize.size()); i++) {
1052 accum += geomSize[i];
1053 fout << accum <<
" ";
1059 fout <<
" </DataArray>" << std::endl;
1060 fout <<
" <DataArray type=\"Int32\" Name=\"types\" format=\"ascii\">" << std::endl;
1062 for (
int i = 0; i < int(geomSize.size()); i++) {
1063 switch (geomSize[i]) {
1081 fout <<
" </DataArray>" << std::endl;
1082 fout <<
" </Cells>" << std::endl;
1085 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1087 fout <<
" </Piece>" << std::endl;
1088 fout <<
" </UnstructuredGrid>" << std::endl;
1089 fout <<
"</VTKFile>" << std::endl;
1092 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1097 pvtu <<
"<VTKFile type=\"PUnstructuredGrid\" byte_order=\"LittleEndian\">" << std::endl;
1098 pvtu <<
" <PUnstructuredGrid GhostLevel=\"0\">" << std::endl;
1099 pvtu <<
" <PPointData Scalars=\"Node Aggregate Processor\">" << std::endl;
1100 pvtu <<
" <PDataArray type=\"Int32\" Name=\"Node\"/>" << std::endl;
1101 pvtu <<
" <PDataArray type=\"Int32\" Name=\"Aggregate\"/>" << std::endl;
1102 pvtu <<
" <PDataArray type=\"Int32\" Name=\"Processor\"/>" << std::endl;
1103 pvtu <<
" </PPointData>" << std::endl;
1104 pvtu <<
" <PPoints>" << std::endl;
1105 pvtu <<
" <PDataArray type=\"Float64\" NumberOfComponents=\"3\"/>" << std::endl;
1106 pvtu <<
" </PPoints>" << std::endl;
1107 for (
int i = 0; i < numProcs; i++) {
1109 pvtu <<
" <Piece Source=\"" <<
replaceAll(baseFname,
"%PROCID",
toString(i)) <<
"\"/>" << std::endl;
1113 for (
int i = 0; i < numProcs; i++) {
1115 pvtu <<
" <Piece Source=\"" << fn.insert(fn.rfind(
".vtu"),
"-finegraph") <<
"\"/>" << std::endl;
1126 pvtu <<
" </PUnstructuredGrid>" << std::endl;
1127 pvtu <<
"</VTKFile>" << std::endl;
1131 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1134 std::ofstream color(
"random-colormap.xml");
1135 color <<
"<ColorMap name=\"MueLu-Random\" space=\"RGB\">" << std::endl;
1138 color <<
" <Point x=\"" << -1 <<
"\" o=\"1\" r=\"1\" g=\"0\" b=\"0\"/>" << std::endl;
1139 color <<
" <Point x=\"" << -2 <<
"\" o=\"1\" r=\"1\" g=\"0.6\" b=\"0\"/>" << std::endl;
1140 color <<
" <Point x=\"" << -3 <<
"\" o=\"1\" r=\"1\" g=\"1\" b=\"0\"/>" << std::endl;
1142 for (
int i = 0; i < 5000; i += 4) {
1143 color <<
" <Point x=\"" << i <<
"\" o=\"1\" r=\"" << (rand() % 50) / 256.0 <<
"\" g=\"" << (rand() % 256) / 256.0 <<
"\" b=\"" << (rand() % 256) / 256.0 <<
"\"/>" << std::endl;
1145 color <<
"</ColorMap>" << std::endl;
1147 }
catch (std::exception& e) {
1149 "VisualizationHelpers::buildColormap: Error while building colormap file: " << e.what());
static void doPointCloud(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes)
MueLu::DefaultLocalOrdinal LocalOrdinal
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
std::string getPVTUFileName(int numProcs, int myRank, int level, const Teuchos::ParameterList &pL) const
void writeFileVTKOpening(std::ofstream &fout, std::vector< int > &uniqueFine, std::vector< int > &geomSizesFine) const
void writeFileVTKCoordinates(std::ofstream &fout, std::vector< int > &uniqueFine, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fx, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fy, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fz, int dim) const
std::string replaceAll(std::string result, const std::string &replaceWhat, const std::string &replaceWithWhat) const
static void doConvexHulls2D(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &yCoords)
T & get(const std::string &name, T def_value)
void writeFileVTKData(std::ofstream &fout, std::vector< int > &uniqueFine, LocalOrdinal myAggOffset, ArrayRCP< LocalOrdinal > &vertex2AggId, int myRank) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void buildColormap() const
std::vector< int > makeUnique(std::vector< int > &vertices) const
replaces node indices in vertices with compressed unique indices, and returns list of unique points ...
std::string getFileName(int numProcs, int myRank, int level, const Teuchos::ParameterList &pL) const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
void writeFileVTKNodes(std::ofstream &fout, std::vector< int > &uniqueFine, Teuchos::RCP< const Map > &nodeMap) const
RCP< ParameterList > GetValidParameterList() const
static int ccw(const myVec2 &a, const myVec2 &b, const myVec2 &c)
static double pointDistFromTri(myVec3 point, myVec3 v1, myVec3 v2, myVec3 v3)
void sort(View &view, const size_t &size)
static double dotProduct(myVec2 v1, myVec2 v2)
void writePVTU(std::ofstream &pvtu, std::string baseFname, int numProcs, bool bFineEdges=false, bool bCoarseEdges=false) const
std::string getBaseFileName(int numProcs, int level, const Teuchos::ParameterList &pL) const
static void doConvexHulls3D(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &yCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &zCoords)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultGlobalOrdinal GlobalOrdinal
static void doJacks(std::vector< int > &vertices, std::vector< int > &geomSizes, LO numLocalAggs, LO numFineNodes, const std::vector< bool > &isRoot, const ArrayRCP< LO > &vertex2AggId)
static myVec2 getNorm(myVec2 v)
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
static myVec3 crossProduct(myVec3 v1, myVec3 v2)
static myVec2 vecSubtract(myVec2 v1, myVec2 v2)
static double distance(myVec2 p1, myVec2 p2)
void writeFileVTKCells(std::ofstream &fout, std::vector< int > &uniqueFine, std::vector< LocalOrdinal > &vertices, std::vector< LocalOrdinal > &geomSize) const
static bool isInFront(myVec3 point, myVec3 inPlane, myVec3 n)
Exception throws to report errors in the internal logical of the program.
static std::vector< myTriangle > processTriangle(std::list< myTriangle > &tris, myTriangle tri, std::list< int > &pointsInFront, myVec3 &barycenter, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &yCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &zCoords)
static double mymagnitude(myVec2 vec)
static void doGraphEdges(std::vector< int > &vertices, std::vector< int > &geomSizes, Teuchos::RCP< LWGraph > &G, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fx, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fy, Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &fz)
void replaceAll(std::string &str, const std::string &from, const std::string &to)
static std::vector< int > giftWrap(std::vector< myVec2 > &points, std::vector< int > &nodes, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &xCoords, const Teuchos::ArrayRCP< const typename Teuchos::ScalarTraits< Scalar >::coordinateType > &yCoords)
void writeFileVTKClosing(std::ofstream &fout) const