25#define _USE_MATH_DEFINES
30#if BITPIT_ENABLE_MPI==1
34#if BITPIT_ENABLE_MPI==1
35#include "bitpit_communications.hpp"
38#include "bitpit_CG.hpp"
39#include "surface_kernel.hpp"
53const std::map<ElementType, unsigned short> SurfaceKernel::m_selectionTypes({
54 {ElementType::QUAD, SurfaceKernel::SELECT_QUAD},
55 {ElementType::TRIANGLE, SurfaceKernel::SELECT_TRIANGLE}
57const unsigned short SurfaceKernel::SELECT_TRIANGLE = 1;
58const unsigned short SurfaceKernel::SELECT_QUAD = 2;
59const unsigned short SurfaceKernel::SELECT_ALL = 3;
61#if BITPIT_ENABLE_MPI==1
80 :
PatchKernel(communicator, haloSize, adaptionMode, partitioningMode)
94#if BITPIT_ENABLE_MPI==1
114 :
PatchKernel(dimension, communicator, haloSize, adaptionMode, partitioningMode)
129#if BITPIT_ENABLE_MPI==1
150 :
PatchKernel(id, dimension, communicator, haloSize, adaptionMode, partitioningMode)
168void SurfaceKernel::initialize()
240 const Cell *cell_ = &m_cells[id];
248 if ((cell_->
getType() == ElementType::UNDEFINED)
249 || (cell_->
getType() == ElementType::VERTEX))
return 0.0;
250 if (cell_->
getType() == ElementType::LINE) {
271 const Cell *cell_ = &m_cells[id];
281 case ElementType::VERTEX:
287 case ElementType::LINE:
299 case ElementType::TRIANGLE:
316 std::size_t nVertices = vertexIds.
size();
317 BITPIT_CREATE_WORKSPACE(vertexCoords, std::array<double BITPIT_COMMA 3>, nVertices, ReferenceElementInfo::MAX_ELEM_VERTICES);
343 const Cell *cell_ = &m_cells[id];
352 if ((cell_->
getType() == ElementType::UNDEFINED)
353 || (cell_->
getType() == ElementType::VERTEX))
return 0.0;
354 if (cell_->
getType() == ElementType::LINE) {
355 return (
norm2(m_vertices[cellVertexIds[0]].getCoords()
356 - m_vertices[cellVertexIds[1]].getCoords()) );
358 std::array<double, 3> d1, d2;
359 if (cell_->
getType() == ElementType::TRIANGLE) {
360 d1 = m_vertices[cellVertexIds[1]].getCoords() - m_vertices[cellVertexIds[0]].getCoords();
361 d2 = m_vertices[cellVertexIds[2]].getCoords() - m_vertices[cellVertexIds[0]].getCoords();
365 int nvert = cellVertexIds.
size();
368 for (
int i = 0; i < nvert; ++i) {
373 const std::array<double, 3> &prevVertexCoords = m_vertices[cellVertexIds[prevVertex]].getCoords();
374 const std::array<double, 3> &vertexCoords = m_vertices[cellVertexIds[vertex]].getCoords();
375 const std::array<double, 3> &nextVertexCoords = m_vertices[cellVertexIds[nextVertex]].getCoords();
377 d1 = nextVertexCoords - vertexCoords;
378 d2 = prevVertexCoords - vertexCoords;
402 const Cell &cell = m_cells[cellId];
413 case ElementType::LINE:
414 case ElementType::VERTEX:
415 case ElementType::UNDEFINED:
424 const Vertex &vertex_0 = m_vertices[faceVertexIds[0]];
425 const Vertex &vertex_1 = m_vertices[faceVertexIds[1]];
452 const Cell *cell_ = &m_cells[id];
461 if ((cell_->
getType() == ElementType::LINE)
462 || (cell_->
getType() == ElementType::VERTEX)
463 || (cell_->
getType() == ElementType::UNDEFINED))
return 0.0;
465 double edge_length = std::numeric_limits<double>::max(), tmp;
467 for (i = 0; i < n_faces; ++i) {
469 if (tmp < edge_length) {
495 const Cell *cell_ = &m_cells[id];
504 if ((cell_->
getType() == ElementType::LINE)
505 || (cell_->
getType() == ElementType::VERTEX)
506 || (cell_->
getType() == ElementType::UNDEFINED))
return 0.0;
508 double edge_length = std::numeric_limits<double>::min(), tmp;
510 for (i = 0; i < n_faces; ++i) {
512 if (tmp > edge_length) {
534 const Cell &cell = m_cells.at(
id);
536 if (cellType == ElementType::UNDEFINED) {
538 }
else if (cellType == ElementType::VERTEX) {
540 }
else if (cellType == ElementType::LINE) {
545 int nCellVertices = cellVertexIds.
size();
550 const std::array<double, 3> &prevVertexCoords = m_vertices[cellVertexIds[prevVertex]].getCoords();
551 const std::array<double, 3> &vertexCoords = m_vertices[cellVertexIds[vertex]].getCoords();
552 const std::array<double, 3> &nextVertexCoords = m_vertices[cellVertexIds[nextVertex]].getCoords();
554 std::array<double, 3> d1 = prevVertexCoords - vertexCoords;
557 std::array<double, 3> d2 = nextVertexCoords - vertexCoords;
560 double angle = std::acos(std::min(1., std::max(-1.,
dotProduct(d1, d2))));
581 const Cell *cell_ = &m_cells[id];
589 if ((cell_->
getType() == ElementType::UNDEFINED)
590 || (cell_->
getType() == ElementType::VERTEX)
591 || (cell_->
getType() == ElementType::LINE))
return 0.0;
593 double angle = std::numeric_limits<double>::max(), tmp;
595 for (
int i = 0; i < n_vert; ++i) {
622 const Cell *cell_ = &m_cells[id];
630 if ((cell_->
getType() == ElementType::UNDEFINED)
631 || (cell_->
getType() == ElementType::VERTEX)
632 || (cell_->
getType() == ElementType::LINE))
return 0.0;
634 double angle = std::numeric_limits<double>::min(), tmp;
636 for (
int i = 0; i < n_vert; ++i) {
664 const Cell *cell_ = &m_cells[id];
672 if ((cell_->
getType() == ElementType::UNDEFINED)
673 || (cell_->
getType() == ElementType::VERTEX)
674 || (cell_->
getType() == ElementType::LINE))
return 0.0;
677 double m_edge = std::numeric_limits<double>::max();
678 double M_edge = std::numeric_limits<double>::min();
680 for (
int i = 0; i < nfaces; ++i) {
682 if (l_edge < m_edge) {
686 M_edge = std::max(M_edge, l_edge);
689 return (M_edge/m_edge);
712 std::array<double, 3> normal = {{0.0, 0.0, 0.0}};
713 const Cell *cell_ = &m_cells[id];
722 if ((cell_->
getType() == ElementType::UNDEFINED)
723 || (cell_->
getType() == ElementType::VERTEX))
return normal;
725 if (cell_->
getType() == ElementType::LINE) {
726 normal = m_vertices[cellVertexIds[1]].getCoords() - m_vertices[cellVertexIds[0]].getCoords();
730 if (cell_->
getType() == ElementType::TRIANGLE) {
731 std::array<double, 3> d1, d2;
732 d1 = m_vertices[cellVertexIds[1]].getCoords() - m_vertices[cellVertexIds[0]].getCoords();
733 d2 = m_vertices[cellVertexIds[2]].getCoords() - m_vertices[cellVertexIds[0]].getCoords();
737 std::array<double, 3> d1, d2;
738 int i, nvert = cellVertexIds.
size();
739 double coeff = 1.0/double(nvert);
740 for (i = 0; i < nvert; ++i) {
745 const std::array<double, 3> &prevVertexCoords = m_vertices[cellVertexIds[prevVertex]].getCoords();
746 const std::array<double, 3> &vertexCoords = m_vertices[cellVertexIds[vertex]].getCoords();
747 const std::array<double, 3> &nextVertexCoords = m_vertices[cellVertexIds[nextVertex]].getCoords();
749 d1 = nextVertexCoords - vertexCoords;
750 d2 = prevVertexCoords - vertexCoords;
754 normal = normal/
norm2(normal);
771 std::array<double, 3> normal;
772 evalEdgeNormals(
id, edge_id, std::numeric_limits<double>::max(), &normal,
nullptr);
790 std::array<double, 3> normal;
792 evalVertexNormals(
id, vertex, vertexNeighs.size(), vertexNeighs.data(), std::numeric_limits<double>::max(), &normal,
nullptr);
812 std::array<double, 3> normal;
813 evalVertexNormals(
id, vertex, nVertexNeighs, vertexNeighs, std::numeric_limits<double>::max(), &normal,
nullptr);
836 std::array<double, 3> normal;
838 evalVertexNormals(
id, vertex, vertexNeighs.size(), vertexNeighs.data(), limit,
nullptr, &normal);
863 std::array<double, 3> normal;
864 evalVertexNormals(
id, vertex, nVertexNeighs, vertexNeighs, limit,
nullptr, &normal);
894 std::array<double, 3> *unlimitedNormal, std::array<double, 3> *limitedNormal)
const
897 if (!unlimitedNormal && !limitedNormal) {
910 if (unlimitedNormal) {
911 *unlimitedNormal = cellVertexAngle * cellNormal;
916 *limitedNormal = cellVertexAngle * cellNormal;
920 for (std::size_t i = 0; i < nVertexNeighs; ++i) {
922 long neighId = vertexNeighs[i];
928 if (unlimitedNormal) {
929 *unlimitedNormal += neighVertexAngle * neighNormal;
942 double misalignment = std::acos(std::min(1.0, std::max(-1.0,
dotProduct(neighNormal, cellNormal))));
943 if (misalignment <= std::abs(limit)) {
944 *limitedNormal += neighVertexAngle * neighNormal;
950 if (unlimitedNormal) {
951 *unlimitedNormal /=
norm2(*unlimitedNormal);
956 *limitedNormal /=
norm2(*limitedNormal);
984 std::array<double, 3> *unlimitedNormal,
985 std::array<double, 3> *limitedNormal)
const
988 if (!unlimitedNormal && !limitedNormal) {
999 if (unlimitedNormal) {
1000 *unlimitedNormal = cellNormal;
1004 if (limitedNormal) {
1005 *limitedNormal = cellNormal;
1009 for (
int i = 0; i < nEdgeNeighs; ++i) {
1011 long neighId = edgeNeighs[i];
1015 if (unlimitedNormal) {
1016 *unlimitedNormal += neighNormal;
1023 if (limitedNormal) {
1029 double misalignment = std::acos(std::min(1.0, std::max(-1.0,
dotProduct(neighNormal, cellNormal))));
1030 if (misalignment <= std::abs(limit)) {
1031 *limitedNormal += neighNormal;
1037 if (unlimitedNormal) {
1038 *unlimitedNormal /=
norm2(*unlimitedNormal);
1042 if (limitedNormal) {
1043 *limitedNormal /=
norm2(*limitedNormal);
1059 alreadyProcessed.
fill(
false);
1061 bool consistent =
true;
1062 std::vector<std::size_t> processRawList;
1065 long seedRawId = seedItr.getRawIndex();
1066 if (alreadyProcessed.
rawAt(seedRawId)) {
1071 processRawList.assign(1, seedRawId);
1072 while (!processRawList.empty()) {
1074 std::size_t cellRawId = processRawList.back();
1075 processRawList.pop_back();
1078 if (alreadyProcessed.
rawAt(cellRawId)) {
1084 const Cell &cell = *cellItr;
1086 for (
int face = 0; face < nCellFaces; ++face) {
1089 for (
int i = 0; i < nFaceAdjacencies; ++i) {
1091 long neighId = faceAdjacencies[i];
1097 bool isNeighConsistent = haveSameOrientation(cell, face, neigh, neighFace);
1098 if (!isNeighConsistent) {
1108 if (!alreadyProcessed.
rawAt(neighRawId)) {
1109 processRawList.push_back(neighRawId);
1121 alreadyProcessed.
rawSet(cellRawId,
true);
1123 if (nUnprocessed == 0) {
1139 if (nUnprocessed == 0) {
1144#if BITPIT_ENABLE_MPI==1
1147 MPI_Allreduce(MPI_IN_PLACE, &consistent, 1, MPI_C_BOOL, MPI_LAND,
getCommunicator());
1173 long firstFacetId = Cell::NULL_ID;
1175 firstFacetId =
getCells().begin()->getId();
1178#if BITPIT_ENABLE_MPI==1
1182 int firstFacetRank = std::numeric_limits<int>::max();
1183 if (firstFacetId >= 0) {
1184 firstFacetRank = patchRank;
1187 MPI_Allreduce(MPI_IN_PLACE, &firstFacetRank, 1, MPI_INT, MPI_MIN,
getCommunicator());
1188 if (patchRank != firstFacetRank) {
1189 firstFacetId = Cell::NULL_ID;
1217#if BITPIT_ENABLE_MPI==1
1222 std::unordered_set<long> flippedCells;
1223 std::unique_ptr<DataCommunicator> ghostCommunicator;
1224 if (ghostExchangeNeeded) {
1228 const int rank = entry.first;
1229 const std::vector<long> &sources = entry.second;
1230 ghostCommunicator->setSend(rank, 2 * sources.size() *
sizeof(
unsigned char));
1234 const int rank = entry.first;
1235 const std::vector<long> &targets = entry.second;
1236 ghostCommunicator->setRecv(rank, 2 * targets.size() *
sizeof(
unsigned char));
1242 std::vector<std::size_t> processRawList;
1243 if (seed != Element::NULL_ID) {
1245 processRawList.push_back(
getCells().find(seed).getRawIndex());
1248#if BITPIT_ENABLE_MPI==1
1249 if (ghostExchangeNeeded) {
1250 flippedCells.insert(seed);
1258 alreadyProcessed.
fill(
false);
1260 bool orientable =
true;
1262 while (!processRawList.empty()) {
1264 std::size_t cellRawId = processRawList.back();
1265 processRawList.pop_back();
1268 if (alreadyProcessed.
rawAt(cellRawId)) {
1274 const Cell &cell = *cellItr;
1276 for (
int face = 0; face < nCellFaces; ++face) {
1279 for (
int i = 0; i < nFaceAdjacencies; ++i) {
1281 long neighId = faceAdjacencies[i];
1284 const Cell &neigh = *neighItr;
1298 bool isNeighOriented = haveSameOrientation(cell, face, neigh, neighFace);
1299 if (!isNeighOriented) {
1300 if (!alreadyProcessed.
rawAt(neighRawId)) {
1302#if BITPIT_ENABLE_MPI==1
1303 if (ghostExchangeNeeded) {
1304 flippedCells.insert(neighId);
1314 if (!alreadyProcessed.
rawAt(neighRawId)) {
1315 processRawList.push_back(neighRawId);
1331 alreadyProcessed.
rawSet(cellRawId,
true);
1335#if BITPIT_ENABLE_MPI==1
1336 if (ghostExchangeNeeded) {
1337 MPI_Allreduce(MPI_IN_PLACE, &orientable, 1, MPI_C_BOOL, MPI_LAND,
getCommunicator());
1345#if BITPIT_ENABLE_MPI==1
1352 if (ghostExchangeNeeded) {
1354 ghostCommunicator->startAllRecvs();
1357 int rank = entry.first;
1358 SendBuffer &buffer = ghostCommunicator->getSendBuffer(rank);
1359 for (
long cellId : entry.second) {
1360 std::size_t cellRawId =
getCells().find(cellId).getRawIndex();
1362 buffer << static_cast<unsigned char>(alreadyProcessed.
rawAt(cellRawId));
1363 if (flippedCells.count(cellId) > 0) {
1364 buffer << static_cast<unsigned char>(1);
1366 buffer << static_cast<unsigned char>(0);
1369 ghostCommunicator->startSend(rank);
1372 int nPendingRecvs = ghostCommunicator->getRecvCount();
1373 while (nPendingRecvs != 0) {
1374 int rank = ghostCommunicator->waitAnyRecv();
1375 RecvBuffer buffer = ghostCommunicator->getRecvBuffer(rank);
1378 unsigned char processed;
1379 buffer >> processed ;
1381 unsigned char ghostFlipped;
1382 buffer >> ghostFlipped;
1384 if (ghostFlipped == 1 || processed == 1) {
1385 std::size_t cellRawId =
getCells().find(cellId).getRawIndex();
1387 if (ghostFlipped == 1) {
1389 processRawList.push_back(cellRawId);
1390 alreadyProcessed.
rawSet(cellRawId,
false);
1391 }
else if (processed == 1) {
1392 if (!alreadyProcessed.
rawAt(cellRawId)) {
1393 processRawList.push_back(cellRawId);
1402 ghostCommunicator->waitAllSends();
1405 flippedCells.clear();
1410 bool completed = processRawList.empty();
1411#if BITPIT_ENABLE_MPI==1
1412 if (ghostExchangeNeeded) {
1413 MPI_Allreduce(MPI_IN_PLACE, &completed, 1, MPI_C_BOOL, MPI_LAND,
getCommunicator());
1446bool SurfaceKernel::haveSameOrientation(
const Cell &cell_A,
int face_A,
const Cell &cell_B,
int face_B)
const
1451 long cellId_A = cell_A.
getId();
1453 std::size_t nCellVertices_A = cellVertexIds_A.
size();
1455 long cellId_B = cell_B.
getId();
1457 std::size_t nCellVertices_B = cellVertexIds_B.
size();
1461 assert(cellDimension < 3);
1473 for (std::size_t i = 0; i < nCellVertices_A; ++i) {
1475 for (std::size_t j = 0; j < nCellVertices_B; ++j) {
1477 if (vertexId_A == vertexId_B) {
1478 if (cellDimension == 2) {
1485 if (nextVertexId_A == nextVertexId_B || previousVertexId_A == previousVertexId_B) {
1487 }
else if (nextVertexId_A == previousVertexId_B || previousVertexId_A == nextVertexId_B) {
1490 }
else if (cellDimension == 1) {
1493 throw std::runtime_error(
"Unable to identify if the factes has the same orientation.");
1521 std::size_t nMaxCellVertices = std::max(nCellVertices_A, nCellVertices_B);
1522 BITPIT_CREATE_WORKSPACE(vertexCoordinates, std::array<double BITPIT_COMMA 3>, nMaxCellVertices, ReferenceElementInfo::MAX_ELEM_VERTICES);
1527 std::array<double, 3> pseudoNormal_A;
1528 std::array<double, 3> pseudoNormal_B;
1529 for (
int i = 0; i < 2; ++i) {
1530 std::array<double, 3> *pseudoNormal;
1531 long firstFaceVertexLocalId;
1532 std::size_t nCellVertices;
1534 pseudoNormal = &pseudoNormal_A;
1535 firstFaceVertexLocalId = faceLocalVertexIds_A[0];
1536 nCellVertices = nCellVertices_A;
1539 pseudoNormal = &pseudoNormal_B;
1540 firstFaceVertexLocalId = faceLocalVertexIds_B[0];
1541 nCellVertices = nCellVertices_B;
1544 assert(nCellVertices >= 3);
1546 const std::array<double, 3> &V_0 = vertexCoordinates[(firstFaceVertexLocalId + 0) % nCellVertices];
1547 const std::array<double, 3> &V_1 = vertexCoordinates[(firstFaceVertexLocalId + 1) % nCellVertices];
1548 for (std::size_t k = 2; k < nCellVertices; ++k) {
1549 const std::array<double, 3> &V_2 = vertexCoordinates[(firstFaceVertexLocalId + k) % nCellVertices];
1552 if (!utils::DoubleFloatingEqual()(
norm2(*pseudoNormal), 0.)) {
1554 }
else if (k == (nCellVertices - 1)) {
1555 throw std::runtime_error(
"Unable to identify the non-collinear vertices.");
1564 std::array<double, 3> windingDirection = {{0., 0., 1.}};
1565 for (
int d = 2; d <= 0; --d) {
1566 windingDirection = {{0., 0., 0.}};
1567 windingDirection[d] = 1.;
1569 double pseudNormalProjection_A =
dotProduct(pseudoNormal_A, windingDirection);
1570 double pseudNormalProjection_B =
dotProduct(pseudoNormal_B, windingDirection);
1571 if (!utils::DoubleFloatingEqual()(pseudNormalProjection_A, 0.) && !utils::DoubleFloatingEqual()(pseudNormalProjection_B, 0.)) {
1573 }
else if (d == 0) {
1574 throw std::runtime_error(
"Unable to identify the relative orientation of the cells.");
1579 int cellWinding_A = (
dotProduct(pseudoNormal_A, windingDirection) > 0.);
1580 int cellWinding_B = (
dotProduct(pseudoNormal_B, windingDirection) > 0.);
1582 return (cellWinding_A == cellWinding_B);
1608 if (cell.
getType() != ElementType::PIXEL) {
1609 int connectBegin = 0;
1610 if (cell.
getType() == ElementType::POLYGON) {
1615 for (
int i = 0; i < (int) std::floor(nCellVertices / 2); ++i) {
1616 std::swap(connectivity[connectBegin + i], connectivity[connectBegin + nCellVertices - i - 1]);
1619 std::swap(connectivity[0], connectivity[1]);
1620 std::swap(connectivity[2], connectivity[3]);
1658 flippedCellAdjacencies.
reserve(nCellFaces, nCellAdjacencies);
1659 flippedCellInterfaces.
reserve(nCellFaces, nCellInterfaces);
1661 if (cell.
getType() != ElementType::PIXEL) {
1670 for (
int i = 0; i < nCellFaces - flipOffset; ++i) {
1672 const long *faceAdjacencies = cell.
getAdjacencies(nCellFaces - i - 1 - flipOffset);
1673 flippedCellAdjacencies.
pushBack(nFaceAdjacencies, faceAdjacencies);
1676 const long *faceInterfaces = cell.
getInterfaces(nCellFaces - i - 1 - flipOffset);
1677 flippedCellInterfaces.
pushBack(nFaceInterfaces, faceInterfaces);
1680 if (flipOffset == 1) {
1682 const long *lastFaceAdjacencies = cell.
getAdjacencies(nCellFaces - 1);
1683 flippedCellAdjacencies.
pushBack(nLastFaceAdjacencies, lastFaceAdjacencies);
1686 const long *lastFaceInterfaces = cell.
getInterfaces(nCellFaces - 1);
1687 flippedCellInterfaces.
pushBack(nLastFaceInterfaces, lastFaceInterfaces);
1690 std::array<int, 4> orderedFaces = {{1, 0, 2, 3}};
1691 for (
int face : orderedFaces) {
1694 flippedCellAdjacencies.
pushBack(nFaceAdjacencies, faceAdjacencies);
1698 flippedCellInterfaces.
pushBack(nFaceInterfaces, faceInterfaces);
1703 if (nCellAdjacencies > 0) {
1711 if (nCellInterfaces > 0) {
1716 for (
int i = 0; i < nCellInterfaces; ++i) {
1717 long interfaceId = cellInterfaces[i];
1718 Interface &
interface = getInterface(interfaceId);
1722 int ownerFace = interface.getOwnerFace();
1723 if (ownerFace != nCellFaces - 1) {
1724 ownerFace = nCellFaces - 2 - ownerFace;
1725 interface.setOwner(
id, ownerFace);
1728 int neighFace = interface.getNeighFace();
1729 if (neighFace != nCellFaces - 1) {
1730 neighFace = nCellFaces - 2 - neighFace;
1731 interface.setNeigh(
id,neighFace);
1751 std::string indent(padding,
' ');
1761 out << indent <<
"Aspect ratio distribution ---------------" << std::endl;
1765 std::vector<double> bins, hist;
1769 SELECT_TRIANGLE | SELECT_QUAD);
1772 displayHistogram(count, bins, hist,
"AR", out, padding + 2);
1776 out << indent <<
"Min. angle distribution -----------------" << std::endl;
1780 std::vector<double> bins, hist;
1784 SELECT_TRIANGLE | SELECT_QUAD);
1787 displayHistogram(count, bins, hist,
"min. angle", out, padding + 2);
1791 out << indent <<
"Max. angle distribution -----------------" << std::endl;
1795 std::vector<double> bins, hist;
1799 SELECT_TRIANGLE | SELECT_QUAD);
1802 displayHistogram(count, bins, hist,
"max. angle", out, padding + 2);
1840 std::vector<double> hist;
1847 if (bins.size() < 2) {
1849 bins.resize(n_intervals+1);
1852 db = (M_ - m_)/
double(n_intervals);
1853 for (
int i = 0; i < n_intervals+1; ++i) {
1854 bins[i] = m_ + db * double(i);
1858 n_intervals = bins.size()-1;
1862 hist.resize(n_intervals+2, 0.0);
1876 for (
auto &cell_ : m_cells) {
1878 if (compareSelectedTypes(mask, cell_.getType())) {
1879 ar = (this->*funct_)(
id, dummy);
1881 while ((bins[i] - ar < 1.0e-5) && (i < n_intervals+1)) ++i;
1888 hist = 100.0 * hist/double(count);
1903void SurfaceKernel::displayHistogram(
1905 const std::vector<double> &bins,
1906 const std::vector<double> &hist,
1907 const std::string &stats_name,
1909 unsigned int padding
1916 int nbins = bins.size();
1918 std::string indent(padding,
' ');
1919 std::stringstream ss;
1929 ss << std::setprecision(3);
1932 out << indent <<
"poll size: " << count << std::endl;
1935 n_fill = ss.str().length();
1936 ss << std::string(std::max(
size_t(0), 6 - n_fill),
' ');
1937 out << ss.str() <<
"%, with " << stats_name <<
" < ";
1940 out << ss.str() << std::endl;
1942 for (i = 0; i < nbins-1; ++i) {
1945 n_fill = ss.str().length();
1946 ss << std::string(std::max(
size_t(0), 6 - n_fill),
' ');
1947 out << ss.str() <<
"%, with ";
1950 n_fill = ss.str().length();
1951 ss << std::string(std::max(
size_t(0), 6 - n_fill),
' ');
1952 out << ss.str() <<
" < " << stats_name <<
" < ";
1955 out << ss.str() << std::endl;
1960 n_fill = ss.str().length();
1961 ss << std::string(std::max(
size_t(0), 6 - n_fill),
' ');
1962 out << ss.str() <<
"%, with ";
1965 n_fill = ss.str().length();
1966 ss << std::string(std::max(
size_t(0), 6 - n_fill),
' ');
1967 out << ss.str() <<
" < " << stats_name << std::endl;
1980bool SurfaceKernel::compareSelectedTypes(
unsigned short mask_,
ElementType type_)
const
1982 unsigned short masked = m_selectionTypes.at(type_);
1983 return ( (mask_ & masked) == masked );
1999 std::size_t nVertices = vertexIds.
size();
2002 for (std::size_t k = 0; k < nVertices; ++k) {
2004 orderedVertexIdsStorage[k] = vertexIds[vertex];
2007 return orderedVertexIds;
2026 switch (facetType) {
2028 case (ElementType::POLYGON):
2035 assert(facetType != ElementType::UNDEFINED);
2061 switch (facetType) {
2063 case (ElementType::POLYGON):
2070 assert(facetType != ElementType::UNDEFINED);
2089 for (std::size_t k = 0; k < nEdges; ++k) {
2093 return orderedEdgeIds;
2112 switch (facetType) {
2114 case (ElementType::POLYGON):
2121 assert(facetType != ElementType::UNDEFINED);
2147 switch (facetType) {
2149 case (ElementType::POLYGON):
2156 assert(facetType != ElementType::UNDEFINED);
The Cell class defines the cells.
void setInterfaces(const std::vector< std::vector< long > > &interfaces)
int getInterfaceCount() const
const long * getAdjacencies() const
const long * getInterfaces() const
int getAdjacencyCount() const
void setAdjacencies(const std::vector< std::vector< long > > &adjacencies)
The DataCommunicator class provides the infrastructure needed to exchange data among processes.
ConstProxyVector< long > getFaceVertexIds(int face) const
static int getDimension(ElementType type)
ElementType getType() const
int findVertex(long vertexId) const
const ReferenceElementInfo & getInfo() const
ConstProxyVector< int > getFaceLocalVertexIds(int face) const
static ConstProxyVector< long > getVertexIds(ElementType type, const long *connectivity)
const long * getConnect() const
long getVertexId(int vertex) const
int getVertexCount() const
Metafunction for generation of a flattened vector of vectors.
void reserve(std::size_t nVectors, std::size_t nItems=0)
The Interface class defines the interfaces among cells.
The PatchKernel class provides an interface for defining patches.
CellConstIterator internalCellConstEnd() const
CellIterator internalBegin()
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeSources() const
PiercedVector< Cell > & getCells()
CellConstIterator internalCellConstBegin() const
const std::unordered_map< int, std::vector< long > > & getGhostCellExchangeTargets() const
bool empty(bool global=true) const
const MPI_Comm & getCommunicator() const
virtual int findAdjoinNeighFace(const Cell &cell, int cellFace, const Cell &neigh) const
CellIterator internalEnd()
bool isPartitioned() const
virtual long getCellCount() const
std::vector< long > findCellVertexNeighs(long id, bool complete=true) const
const std::array< double, 3 > & getVertexCoords(long id) const
void extractEnvelope(PatchKernel &envelope) const
long getInternalCellCount() const
ConstProxyVector< std::array< double BITPIT_COMMA 3 > > getCellVertexCoordinates(long id) const
std::size_t getRawIndex() const noexcept
Iterator for the class PiercedStorage.
Metafunction for generating a pierced storage.
__PS_REFERENCE__ rawAt(std::size_t pos, std::size_t offset=0)
void fill(const value_t &value)
void rawSet(std::size_t pos, const value_t &value)
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
container_type::pointer storage_pointer
__PXV_POINTER__ data() noexcept
__PXV_STORAGE_POINTER__ storedData() noexcept
Buffer to be used for receive communications.
The Reference2DElementInfo class allows to define information about reference two-dimensional element...
virtual int getCCWOrderedVertex(int n) const
virtual int getCCWOrderedFace(int n) const
virtual bool areVerticesCCWOrdered() const
virtual bool areFacesCCWOrdered() const
Buffer to be used for send communications.
The SurfaceKernel class provides an interface for defining surface patches.
int getVolumeCodimension() const override
int getPointCodimension() const override
int getFacetOrderedLocalEdge(const Cell &facet, std::size_t n) const
virtual void evalVertexNormals(long id, int vertex, std::size_t nVertexNeighs, const long *vertexNeighs, double limit, std::array< double, 3 > *unlimitedNormal, std::array< double, 3 > *limitedNormal) const
void displayQualityStats(std::ostream &, unsigned int padding=0) const
virtual double evalAspectRatio(long, int &) const
virtual double evalMinEdgeLength(long, int &) const
void flipCellOrientation(long id)
bool areFacetVerticesOrdered(const Cell &facet) const
int getLineCodimension() const override
std::vector< double > computeHistogram(eval_f_ funct_, std::vector< double > &bins, long &count, int n_intervals=8, unsigned short mask=SELECT_ALL) const
void extractEnvelope(LineKernel &envelope) const
ConstProxyVector< long > getFacetOrderedEdgeIds(const Cell &facet) const
int getSurfaceCodimension() const override
virtual double evalMaxAngleAtVertex(long, int &) const
virtual std::array< double, 3 > evalFacetNormal(long, const std::array< double, 3 > &orientation={{0., 0., 1.}}) const
int getFacetOrderedLocalVertex(const Cell &facet, std::size_t n) const
SurfaceKernel(MPI_Comm communicator, std::size_t haloSize, AdaptionMode adaptionMode, PartitioningMode partitioningMode)
bool areFacetEdgesOrdered(const Cell &facet) const
bool isCellOrientationConsistent() const
std::array< double, 3 > evalEdgeNormal(long, int) const
ConstProxyVector< long > getFacetOrderedVertexIds(const Cell &facet) const
std::array< double, 3 > evalLimitedVertexNormal(long, int, double) const
virtual double evalCellArea(long) const
void evalBarycentricCoordinates(long id, const std::array< double, 3 > &point, double *lambda) const
virtual void evalEdgeNormals(long id, int edge, double limit, std::array< double, 3 > *unlimitedNormal, std::array< double, 3 > *limitedNormal) const
virtual double evalMaxEdgeLength(long, int &) const
virtual double evalMinAngleAtVertex(long, int &) const
double evalCellSize(long id) const override
std::array< double, 3 > evalVertexNormal(long, int) const
virtual double evalAngleAtVertex(long, int) const
bool adjustCellOrientation()
virtual double evalEdgeLength(long, int) const
The Vertex class defines the vertexs.
std::array< double, 3 > & getCoords()
array3D projectPointTriangle(array3D const &, array3D const &, array3D const &, array3D const &)
array3D projectPointSegment(array3D const &, array3D const &, array3D const &)
array3D projectPointPolygon(array3D const &, std::vector< array3D > const &)
std::array< T, 3 > crossProduct(const std::array< T, 3 > &x, const std::array< T, 3 > &y)
T dotProduct(const std::array< T, d > &x, const std::array< T, d > &y)
double norm2(const std::array< T, d > &x)
#define BITPIT_UNUSED(variable)
#define BITPIT_CREATE_WORKSPACE(workspace, item_type, size, stack_size)