29#include "bitpit_common.hpp"
30#include "bitpit_CG.hpp"
31#include "bitpit_operators.hpp"
44IBinaryStream& operator>>(IBinaryStream &buffer, Element &element)
55 element._initialize(
id, type);
56 connectSize = element.getConnectSize();
58 buffer >> connectSize;
59 element._initialize(
id, type, connectSize);
63 buffer.read(
reinterpret_cast<char *
>(element.m_connect.get()), connectSize *
sizeof(
long));
81OBinaryStream&
operator<<(OBinaryStream &buffer,
const Element &element)
83 buffer << element.getType();
84 buffer << element.getId();
86 int connectSize = element.getConnectSize();
88 buffer << connectSize;
91 buffer.write(
reinterpret_cast<const char *
>(element.m_connect.get()), connectSize *
sizeof(
long));
93 buffer << element.getPID();
112Element::Tesselation::Tesselation()
124int Element::Tesselation::importVertexCoordinates(
const std::array<double, 3> &coordinates)
126 return importVertexCoordinates(std::array<double, 3>(coordinates));
136int Element::Tesselation::importVertexCoordinates(std::array<double, 3> &&coordinates)
138 m_coordinates.push_back(std::move(coordinates));
140 return (m_coordinates.size() - 1);
151std::vector<int> Element::Tesselation::importVertexCoordinates(
const std::array<double, 3> *coordinates,
int nVertices)
153 int nStoredVertices = m_coordinates.size();
154 m_coordinates.reserve(nStoredVertices + nVertices);
156 std::vector<int> ids(nVertices);
157 for (
int k = 0; k < nVertices; ++k) {
158 m_coordinates.push_back(coordinates[k]);
159 ids[k] = nStoredVertices++;
170void Element::Tesselation::importPolygon(
const std::vector<int> &vertexIds)
172 int nVertices = vertexIds.size();
173 if (nVertices == 3 || nVertices == 4) {
175 m_types.push_back(nVertices == 3 ? ElementType::TRIANGLE :
ElementType::QUAD);
176 m_connects.push_back(vertexIds);
182 std::array<double, 3> centroid = {{0., 0., 0.}};
183 for (
int k = 0; k < nVertices; ++k) {
184 centroid += m_coordinates[vertexIds[k]];
186 centroid = centroid / double(nVertices);
188 int centroidId = importVertexCoordinates(std::move(centroid));
195 int nTileVertices = ReferenceElementInfo::getInfo(tileType).nVertices;
196 int nSideVertices = ReferenceElementInfo::getInfo(ElementType::LINE).nVertices;
198 int nSides = nVertices;
199 m_types.resize(m_nTiles + nSides, tileType);
200 m_connects.resize(m_nTiles + nSides, std::vector<int>(nTileVertices));
201 for (
int i = 0; i < nSides; ++i) {
203 for (
int k = 0; k < nSideVertices; ++k) {
204 m_connects[m_nTiles - 1][k] = vertexIds[(i + k) % nVertices];
206 m_connects[m_nTiles - 1][nSideVertices] = centroidId;
216void Element::Tesselation::importPolyhedron(
const std::vector<int> &vertexIds,
const std::vector<std::vector<int>> &faceVertexIds)
218 int nFaces = faceVertexIds.size();
219 int nVertices = vertexIds.size();
222 int nInitialTiles = m_nTiles;
223 for (
int i = 0; i < nFaces; ++i) {
224 importPolygon(faceVertexIds[i]);
226 int nFinalTiles = m_nTiles;
229 std::array<double, 3> centroid = {{0., 0., 0.}};
230 for (
int k = 0; k < nVertices; ++k) {
231 centroid += m_coordinates[vertexIds[k]];
233 centroid = centroid / double(nVertices);
235 int centroidTesselationId = importVertexCoordinates(std::move(centroid));
244 for (
int i = nInitialTiles; i < nFinalTiles; ++i) {
247 if (tileType == ElementType::TRIANGLE) {
248 tileType = ElementType::TETRA;
249 }
else if (tileType == ElementType::QUAD) {
250 tileType = ElementType::PYRAMID;
253 throw std::runtime_error (
"Unsupported tile");
258 if (tileType == ElementType::TETRA) {
259 std::swap(m_connects[i][0], m_connects[i][2]);
260 }
else if (tileType == ElementType::PYRAMID) {
261 std::swap(m_connects[i][1], m_connects[i][3]);
265 m_connects[i].push_back(centroidTesselationId);
274int Element::Tesselation::getTileCount()
const
285ElementType Element::Tesselation::getTileType(
int tile)
const
287 return m_types[tile];
296std::vector<std::array<double, 3>> Element::Tesselation::getTileVertexCoordinates(
int tile)
const
299 const int nTileVertices = ReferenceElementInfo::getInfo(tileType).nVertices;
300 const std::vector<int> &tileConnect = m_connects[tile];
302 std::vector<std::array<double, 3>> coordinates(nTileVertices);
303 for (
int i = 0; i < nTileVertices; ++i) {
304 coordinates[i] = m_coordinates[tileConnect[i]];
320const long Element::NULL_ID = std::numeric_limits<long>::min();
327 _initialize(NULL_ID, ElementType::UNDEFINED);
340 _initialize(
id, type, connectSize);
351Element::Element(
long id,
ElementType type, std::unique_ptr<
long[]> &&connectStorage)
353 _initialize(
id, type, std::move(connectStorage));
364 if (other.m_connect) {
370 _initialize(other.m_id, other.m_type, connectSize);
374 if (other.m_connect) {
375 std::copy(other.m_connect.get(), other.m_connect.get() + connectSize, m_connect.get());
401 std::swap(other.m_id, m_id);
402 std::swap(other.m_type, m_type);
403 std::swap(other.m_pid, m_pid);
404 std::swap(other.m_connect, m_connect);
415void Element::initialize(
long id,
ElementType type,
int connectSize)
417 _initialize(
id, type, connectSize);
428void Element::initialize(
long id,
ElementType type, std::unique_ptr<
long[]> &&connectStorage)
430 _initialize(
id, type, std::move(connectStorage));
441void Element::_initialize(
long id,
ElementType type,
int connectSize)
444 int previousConnectSize = 0;
447 previousConnectSize = getInfo().nVertices;
452 if (ReferenceElementInfo::hasInfo(type)) {
453 connectSize = ReferenceElementInfo::getInfo(type).nVertices;
456 std::unique_ptr<long[]> connectStorage;
457 if (connectSize != previousConnectSize) {
458 connectStorage = std::unique_ptr<long[]>(
new long[connectSize]);
460 connectStorage = std::move(m_connect);
464 _initialize(
id, type, std::move(connectStorage));
475void Element::_initialize(
long id, ElementType type, std::unique_ptr<
long[]> &&connectStorage)
487 setConnect(std::move(connectStorage));
498void Element::setId(
long id)
510long Element::getId()
const
521bool Element::hasInfo()
const
523 return ReferenceElementInfo::hasInfo(m_type);
533 return ReferenceElementInfo::getInfo(m_type);
566void Element::setPID(
int pid)
581int Element::getPID()
const
591void Element::setConnect(std::unique_ptr<
long[]> &&connect)
593 m_connect = std::move(connect);
599void Element::unsetConnect()
601 m_connect.reset(
nullptr);
609const long * Element::getConnect()
const
611 return m_connect.get();
619long * Element::getConnect()
621 return m_connect.get();
629int Element::getConnectSize()
const
633 case (ElementType::POLYGON):
634 return 1 + getVertexCount();
636 case (ElementType::POLYHEDRON):
637 return getFaceStreamSize();
640 assert(m_type != ElementType::UNDEFINED);
642 return getVertexCount();
655bool Element::hasSameConnect(
const Element &other)
const
657 int cellConnectSize = getConnectSize();
662 const long *cellConnect = getConnect();
663 const long *otherConnect = other.
getConnect();
664 for (
int k = 0; k < cellConnectSize; ++k) {
665 if (cellConnect[k] != otherConnect[k]) {
678int Element::getFaceCount()
const
682 case (ElementType::POLYGON):
683 return countPolygonFaces(getConnect());
685 case (ElementType::POLYHEDRON):
686 return countPolyhedronFaces(getConnect());
689 assert(m_type != ElementType::UNDEFINED);
691 return getInfo().nFaces;
705 case (ElementType::POLYGON):
707 return ElementType::LINE;
710 case (ElementType::POLYHEDRON):
712 int nFaceVertices = getFaceVertexCount(face);
713 switch (nFaceVertices) {
716 return ElementType::TRIANGLE;
719 return ElementType::QUAD;
722 return ElementType::POLYGON;
729 assert(m_type != ElementType::UNDEFINED);
731 return getInfo().faceTypeStorage[face];
743int Element::getFaceVertexCount(
int face)
const
747 case (ElementType::POLYHEDRON):
749 const long *connectivity = getConnect();
750 int facePos = getFaceStreamPosition(connectivity, face);
752 return connectivity[facePos];
757 assert(m_type != ElementType::UNDEFINED);
761 return ReferenceElementInfo::getInfo(faceType).nVertices;
777 case (ElementType::POLYGON):
779 int nVertices = getVertexCount();
781 int faceConnectSize = getFaceVertexCount(face);
785 for (
int i = 0; i < faceConnectSize; ++i) {
786 localFaceConnectStorage[i] = (face + i) % nVertices;
789 return localFaceConnect;
792 case (ElementType::POLYHEDRON):
796 bool faceHasReferenceInfo = ReferenceElementInfo::hasInfo(faceType);
800 int nFaceVertices = faceVertexIds.
size();
806 int faceConnectSize = nFaceVertices;
807 int localVertexOffset = 0;
808 if (!faceHasReferenceInfo) {
815 if (!faceHasReferenceInfo) {
816 localFaceConnectStorage[0] = nFaceVertices;
819 for (
int k = 0; k < nFaceVertices; ++k) {
820 int vertexId = faceVertexIds[k];
821 auto localVertexIdItr = std::find(vertexIds.
begin(), vertexIds.
end(), vertexId);
822 assert(localVertexIdItr != vertexIds.
end() && *localVertexIdItr == vertexId);
823 localFaceConnectStorage[localVertexOffset + k] =
static_cast<int>(std::distance(vertexIds.
begin(), localVertexIdItr));
826 return localFaceConnect;
831 assert(m_type != ElementType::UNDEFINED);
833 const int localConnectSize = getFaceVertexCount(face);
834 const int *localFaceConnect = getInfo().faceConnectStorage[face].data();
850 const long *connectivity = getConnect();
854 case (ElementType::POLYGON):
856 int connectSize = getConnectSize();
858 int facePos = 1 + face;
859 int faceConnectSize = getFaceVertexCount(face);
860 if (facePos + faceConnectSize <= connectSize) {
865 for (
int i = 0; i < faceConnectSize; ++i) {
866 int position = facePos + i;
867 if (position >= connectSize) {
868 position = position % connectSize + 1;
871 faceConnectStorage[i] = connectivity[position];
878 case (ElementType::POLYHEDRON):
882 int facePos = getFaceStreamPosition(connectivity, face);
883 int faceConnectSize = connectivity[facePos];
884 int faceConnectBegin = facePos + 1;
885 if (!ReferenceElementInfo::hasInfo(faceType)) {
895 assert(m_type != ElementType::UNDEFINED);
900 int faceConnectSize = getFaceVertexCount(face);
901 const int *localFaceConnect = getInfo().faceConnectStorage[face].data();
905 for (
int k = 0; k < faceConnectSize; ++k) {
906 int localVertexId = localFaceConnect[k];
907 long vertexId = connectivity[localVertexId];
908 faceConnectStorage[k] = vertexId;
922int Element::getEdgeCount()
const
926 case (ElementType::POLYGON):
928 return getVertexCount();
931 case (ElementType::POLYHEDRON):
933 int nVertices = getVertexCount();
934 int nFaces = getFaceCount();
935 int nEdges = nVertices + nFaces - 2;
942 assert(m_type != ElementType::UNDEFINED);
944 return getInfo().nEdges;
959 int dimension = getDimension();
963 return ElementType::UNDEFINED;
967 return ElementType::VERTEX;
970 return ElementType::LINE;
981int Element::getEdgeVertexCount(
int edge)
const
985 return ReferenceElementInfo::getInfo(edgeType).nVertices;
998 case (ElementType::POLYGON):
1000 int nEdgeVertices = ReferenceElementInfo::getInfo(ElementType::VERTEX).nVertices;
1004 for (
int k = 0; k < nEdgeVertices; ++k) {
1005 localEdgeConnectStorage[k] = k;
1008 return localEdgeConnect;
1011 case (ElementType::POLYHEDRON):
1015 int nEdgeVertices = edgeVertexIds.
size();
1023 for (
int k = 0; k < nEdgeVertices; ++k) {
1024 int vertexId = edgeVertexIds[k];
1025 auto localVertexIdItr = std::find(vertexIds.
begin(), vertexIds.
end(), vertexId);
1026 assert(localVertexIdItr != vertexIds.
end() && *localVertexIdItr == vertexId);
1027 localEdgeConnectStorage[k] =
static_cast<int>(std::distance(vertexIds.
begin(), localVertexIdItr));
1030 return localEdgeConnect;
1035 assert(m_type != ElementType::UNDEFINED);
1037 const int localConnectSize = getEdgeVertexCount(edge);
1038 const int *localEdgeConnect = getInfo().edgeConnectStorage[edge].data();
1054 const long *connectivity = getConnect();
1058 case (ElementType::POLYGON):
1063 case (ElementType::POLYHEDRON):
1065 std::vector<ConstProxyVector<long>> edgeConnectStorage = evalEdgeConnects(edge + 1);
1067 return edgeConnectStorage[edge];
1072 assert(m_type != ElementType::UNDEFINED);
1075 int nEdgeVertices = localEdgeConnect.
size();
1079 for (
int k = 0; k < nEdgeVertices; ++k) {
1080 int localVertexId = localEdgeConnect[k];
1081 edgeConnectStorage[k] = connectivity[localVertexId];
1100 case ElementType::POLYGON:
1103 case ElementType::POLYHEDRON:
1107 assert(type != ElementType::UNDEFINED);
1109 return ReferenceElementInfo::getInfo(type).dimension;
1119int Element::getDimension()
const
1121 return getDimension(m_type);
1133 return (getDimension(type) == 3);
1142bool Element::isThreeDimensional()
const
1144 return (getDimension() == 3);
1152int Element::getVertexCount()
const
1156 case (ElementType::POLYGON):
1158 return countPolygonVertices(getConnect());
1161 case (ElementType::POLYHEDRON):
1163 return getVertexIds().size();
1168 assert(m_type != ElementType::UNDEFINED);
1170 return getInfo().nVertices;
1183 return getVertexIds(m_type, getConnect());
1197 case (ElementType::POLYGON):
1202 case (ElementType::POLYHEDRON):
1204 int nFaces = countPolyhedronFaces(connectivity);
1215 std::unordered_map<long, std::size_t> uniqueVertexIds;
1216 for (
int i = 0; i < nFaces; ++i) {
1217 int facePos = getFaceStreamPosition(connectivity, i);
1219 int beginVertexPos = facePos + 1;
1220 int endVertexPos = facePos + 1 + connectivity[facePos];
1221 for (
int vertexPos = beginVertexPos; vertexPos < endVertexPos; ++vertexPos) {
1222 long vertexId = connectivity[vertexPos];
1223 if (uniqueVertexIds.count(vertexId) != 0) {
1227 std::size_t vertexSortIndex = uniqueVertexIds.size();
1228 uniqueVertexIds.insert({vertexId, vertexSortIndex});
1236 std::size_t nVertices = uniqueVertexIds.size();
1240 for (
const auto &vertexEntry : uniqueVertexIds) {
1241 long vertexId = vertexEntry.first;
1242 std::size_t vertexSortIndex = vertexEntry.second;
1243 vertexIdsStorage[vertexSortIndex] = vertexId;
1251 assert(type != ElementType::UNDEFINED);
1269long Element::getVertexId(
int vertex)
const
1273 case (ElementType::POLYGON):
1274 case (ElementType::POLYHEDRON):
1278 return vertexIds[vertex];
1283 assert(m_type != ElementType::UNDEFINED);
1285 const long *connectivity = getConnect();
1287 return connectivity[vertex];
1302int Element::findVertex(
long vertexId)
const
1306 auto localVertexItr = std::find(cellVertexIds.
begin(), cellVertexIds.
end(), vertexId);
1307 if (localVertexItr == cellVertexIds.
end()) {
1311 return static_cast<int>(std::distance(cellVertexIds.
begin(), localVertexItr));
1323 if (m_type == ElementType::POLYHEDRON) {
1325 if (faceType == ElementType::POLYGON) {
1327 vertexIds.
set(vertexIds.
data() + 1, vertexIds.
size() - 1);
1343long Element::getFaceVertexId(
int face,
int vertex)
const
1347 case (ElementType::POLYGON):
1348 case (ElementType::POLYHEDRON):
1352 return faceVertexIds[vertex];
1360 return cellVertexIds[faceLocalVertexIds[vertex]];
1376 case (ElementType::POLYHEDRON):
1379 if (faceType != ElementType::POLYGON) {
1380 return getFaceLocalConnect(face);
1384 std::size_t faceLocalConnectSize = faceLocalConnect.
size();
1386 std::size_t nFaceVertices = faceLocalConnectSize - 1;
1389 for (std::size_t i = 0; i < nFaceVertices; ++i) {
1390 faceLocalVertexIdsStorage[i] = faceLocalConnect[i + 1];
1393 return faceLocalVertexIds;
1398 return getFaceLocalConnect(face);
1412 return getEdgeConnect(edge);
1424long Element::getEdgeVertexId(
int edge,
int vertex)
const
1428 return edgeVertexIds[vertex];
1439 return getEdgeLocalConnect(edge);
1451int Element::renumberVertices(
const std::unordered_map<long, long> &map)
1453 int nRenumberedVertices = 0;
1456 case ElementType::POLYGON:
1458 int nVertices = getVertexCount();
1459 long *connectivity = getConnect();
1460 for (
int k = 1; k < nVertices + 1; ++k) {
1461 auto mapItr = map.find(connectivity[k]);
1462 if (mapItr != map.end()) {
1463 connectivity[k] = mapItr->second;
1464 ++nRenumberedVertices;
1471 case ElementType::POLYHEDRON:
1473 int nFaces = getFaceCount();
1474 long *connectivity = getConnect();
1476 for (
int i = 0; i < nFaces; ++i) {
1477 int facePos = getFaceStreamPosition(connectivity, i);
1479 int beginVertexPos = facePos + 1;
1480 int endVertexPos = facePos + 1 + connectivity[facePos];
1481 for (
int k = beginVertexPos; k < endVertexPos; ++k) {
1482 auto mapItr = map.find(connectivity[k]);
1483 if (mapItr != map.end()) {
1484 connectivity[k] = mapItr->second;
1485 ++nRenumberedVertices;
1495 assert(m_type != ElementType::UNDEFINED);
1497 int nVertices = getVertexCount();
1498 long *connectivity = getConnect();
1499 for (
int k = 0; k < nVertices; ++k) {
1500 auto mapItr = map.find(connectivity[k]);
1501 if (mapItr != map.end()) {
1502 connectivity[k] = mapItr->second;
1503 ++nRenumberedVertices;
1512 return nRenumberedVertices;
1521std::array<double, 3> Element::evalCentroid(
const std::array<double, 3> *coordinates)
const
1523 int nVertices = getVertexCount();
1524 if (nVertices == 0) {
1525 return {{0., 0., 0.}};
1528 std::array<double, 3> centroid = coordinates[0];
1529 for (
int i = 1; i < nVertices; ++i) {
1530 const std::array<double, 3> &vertexCoordinates = coordinates[i];
1531 for (
int k = 0; k < 3; ++k) {
1532 centroid[k] += vertexCoordinates[k];
1536 for (
int k = 0; k < 3; ++k) {
1537 centroid[k] /= nVertices;
1549double Element::evalSize(
const std::array<double, 3> *coordinates)
const
1553 case ElementType::POLYHEDRON:
1557 int nFaces = getFaceCount();
1558 BITPIT_CREATE_WORKSPACE(faceVertexCoords, std::array<double BITPIT_COMMA 3>, getVertexCount(), ReferenceElementInfo::MAX_ELEM_VERTICES);
1560 double volume = evalVolume(coordinates);
1562 double faceMaxArea = 0;
1563 for (
int face = 0; face < nFaces; ++face) {
1565 bool faceHasReferenceInfo = ReferenceElementInfo::hasInfo(faceType);
1568 for (
int n = 0; n < getFaceVertexCount(face); ++n) {
1569 faceVertexCoords[n] = coordinates[faceLocalVertexIds[n]];
1573 if (faceHasReferenceInfo) {
1575 faceArea = faceInfo.evalArea(faceVertexCoords);
1578 std::size_t faceConnectSize = faceConnect.
size();
1580 Element faceElement(0, faceType, faceConnect.
size());
1581 long *faceElementConnect = faceElement.
getConnect();
1582 for (std::size_t i = 0; i < faceConnectSize; ++i) {
1583 faceElementConnect[i] = faceConnect[i];
1586 faceArea = faceElement.
evalArea(faceVertexCoords);
1588 faceMaxArea = std::max(faceArea, faceMaxArea);
1591 double size = volume / faceMaxArea;
1596 case ElementType::POLYGON:
1600 int nFaces = getFaceCount();
1601 BITPIT_CREATE_WORKSPACE(faceVertexCoords, std::array<double BITPIT_COMMA 3>, getVertexCount(), ReferenceElementInfo::MAX_ELEM_VERTICES);
1603 double area = evalArea(coordinates);
1605 double faceMaxLength = 0;
1606 for (
int face = 0; face < nFaces; ++face) {
1608 assert(ReferenceElementInfo::hasInfo(faceType));
1611 for (
int n = 0; n < getFaceVertexCount(face); ++n) {
1612 faceVertexCoords[n] = coordinates[faceLocalVertexIds[n]];
1616 faceMaxLength = std::max(faceInfo.evalLength(faceVertexCoords), faceMaxLength);
1619 double size = area / faceMaxLength;
1624 case ElementType::UNDEFINED:
1633 return referenceInfo.evalSize(coordinates);
1646double Element::evalVolume(
const std::array<double, 3> *coordinates)
const
1650 case ElementType::POLYHEDRON:
1652 Tesselation tesselation = generateTesselation(coordinates);
1653 int nTiles = tesselation.getTileCount();
1656 for (
int i = 0; i < nTiles; ++i) {
1657 ElementType tileType = tesselation.getTileType(i);
1658 const std::vector<std::array<double, 3>> tileCoordinates = tesselation.getTileVertexCoordinates(i);
1661 volume += referenceInfo.evalVolume(tileCoordinates.data());
1669 assert(getDimension() == 3);
1673 return referenceInfo.evalVolume(coordinates);
1685double Element::evalArea(
const std::array<double, 3> *coordinates)
const
1689 case ElementType::POLYGON:
1691 Tesselation tesselation = generateTesselation(coordinates);
1692 int nTiles = tesselation.getTileCount();
1695 for (
int i = 0; i < nTiles; ++i) {
1696 ElementType tileType = tesselation.getTileType(i);
1697 const std::vector<std::array<double, 3>> tileCoordinates = tesselation.getTileVertexCoordinates(i);
1700 area += referenceInfo.evalArea(tileCoordinates.data());
1708 assert(getDimension() == 2);
1712 return referenceInfo.evalArea(coordinates);
1724double Element::evalLength(
const std::array<double, 3> *coordinates)
const
1728 case ElementType::POLYGON:
1729 case ElementType::POLYHEDRON:
1730 case ElementType::UNDEFINED:
1737 assert(getDimension() == 1);
1741 return referenceInfo.evalLength(coordinates);
1759std::array<double, 3> Element::evalNormal(
const std::array<double, 3> *coordinates,
1760 const std::array<double, 3> &orientation,
1761 const std::array<double, 3> &point)
const
1765 case ElementType::POLYGON:
1771 int dimension = getDimension();
1773 Tesselation tesselation = generateTesselation(coordinates);
1774 int nTiles = tesselation.getTileCount();
1776 std::array<double, 3> normal = {{0., 0., 0.}};
1777 for (
int i = 0; i < nTiles; ++i) {
1778 ElementType tileType = tesselation.getTileType(i);
1779 const std::vector<std::array<double, 3>> tileCoordinates = tesselation.getTileVertexCoordinates(i);
1782 double tileArea = referenceInfo.evalArea(tileCoordinates.data());
1783 std::array<double, 3> tileNormal = {{0., 0., 0.}};
1784 if (dimension == 2) {
1785 tileNormal = referenceInfo.evalNormal(tileCoordinates.data(), point);
1786 }
else if (dimension == 1) {
1788 tileNormal = referenceInfo1D.evalNormal(tileCoordinates.data(), orientation, point);
1789 }
else if (dimension == 0) {
1790 tileNormal = orientation;
1793 normal += tileArea * tileNormal;
1795 normal /=
norm2(normal);
1802 assert(getDimension() != 3);
1804 int dimension = getDimension();
1805 if (dimension == 2) {
1808 return referenceInfo.evalNormal(coordinates, point);
1809 }
else if (dimension == 1) {
1812 return referenceInfo.evalNormal(coordinates, orientation, point);
1828double Element::evalPointDistance(
const std::array<double, 3> &point,
const std::array<double, 3> *coordinates)
const
1831 std::array<double, 3> projection;
1832 evalPointProjection(point, coordinates, &projection, &distance);
1846void Element::evalPointProjection(
const std::array<double, 3> &point,
const std::array<double, 3> *coordinates,
1847 std::array<double, 3> *projection,
double *distance)
const
1851 case ElementType::POLYGON:
1854 *distance = CGElem::distancePointPolygon(point, getVertexCount(), coordinates, *projection, projectionFlag);
1859 case ElementType::POLYHEDRON:
1861 *distance = std::numeric_limits<double>::max();
1863 int nFaces = getFaceCount();
1864 std::vector<std::array<double, 3>> faceCoordinates;
1865 for (
int i = 0; i < nFaces; ++i) {
1868 int nFaceVertices = faceVertexIds.
size();
1869 faceCoordinates.resize(nFaceVertices);
1870 for (
int k = 0; k < nFaceVertices; ++k) {
1871 faceCoordinates[k] = coordinates[faceVertexIds[k]];
1874 double faceDistance;
1875 std::array<double, 3> faceProjection;
1876 bool faceHasReferenceInfo = ReferenceElementInfo::hasInfo(faceType);
1877 if (faceHasReferenceInfo) {
1878 ReferenceElementInfo::getInfo(faceType).evalPointProjection(point, faceCoordinates.data(), &faceProjection, &faceDistance);
1880 int faceProjectionFlag;
1881 faceDistance = CGElem::distancePointPolygon(point, nFaceVertices, faceCoordinates.data(), faceProjection, faceProjectionFlag);
1884 if (faceDistance < *distance) {
1885 *distance = faceDistance;
1886 *projection = faceProjection;
1895 assert(ReferenceElementInfo::hasInfo(m_type));
1897 getInfo().evalPointProjection(point, coordinates, projection, distance);
1911Element::Tesselation Element::generateTesselation(
const std::array<double, 3> *coordinates)
const
1916 int nVertices = getVertexCount();
1917 std::vector<int> vertexTesselationIds = tesselation.importVertexCoordinates(coordinates, nVertices);
1923 case ElementType::POLYGON:
1925 tesselation.importPolygon(vertexTesselationIds);
1930 case ElementType::POLYHEDRON:
1932 int nFaces = getFaceCount();
1933 std::vector<std::vector<int>> faceTesselationIds(nFaces);
1934 for (
int i = 0; i < nFaces; ++i) {
1935 ConstProxyVector<int> localVertexIds = getFaceLocalVertexIds(i);
1936 int nFaceVertices = localVertexIds.size();
1937 faceTesselationIds[i].resize(nFaceVertices);
1938 for (
int k = 0; k < nFaceVertices; ++k) {
1939 faceTesselationIds[i][k] = vertexTesselationIds[localVertexIds[k]];
1943 tesselation.importPolyhedron(vertexTesselationIds, faceTesselationIds);
1950 assert(ReferenceElementInfo::hasInfo(type));
1952 tesselation.m_nTiles = 1;
1953 tesselation.m_types.push_back(type);
1954 tesselation.m_connects.push_back(vertexTesselationIds);
1969int Element::getFaceStreamSize()
const
1971 int nFaces = getFaceCount();
1972 int size = 1 + (getFaceStreamPosition(nFaces) - 1);
1982std::vector<long> Element::getFaceStream()
const
1984 int nFaces = getFaceCount();
1985 int faceStreamSize = getFaceStreamSize();
1986 std::vector<long> faceStream(faceStreamSize);
1989 faceStream[pos] = nFaces;
1990 for (
int i = 0; i < nFaces; ++i) {
1992 int nFaceVertices = faceVertexIds.
size();
1995 faceStream[pos] = getFaceVertexCount(i);
1996 for (
int k = 0; k < nFaceVertices; ++k) {
1998 faceStream[pos] = faceVertexIds[k];
2015 int nFaces = (*faceStream)[pos];
2016 for (
int i = 0; i < nFaces; ++i) {
2018 int nFaceVertices = (*faceStream)[pos];
2019 for (
int k = 0; k < nFaceVertices; ++k) {
2021 auto mapItr = map.
find((*faceStream)[pos]);
2022 if (mapItr != map.
end()) {
2023 (*faceStream)[pos] = *mapItr;
2035int Element::getFaceStreamPosition(
int face)
const
2037 return getFaceStreamPosition(getConnect(), face);
2047int Element::getFaceStreamPosition(
const long *connectivity,
int face)
2050 for (
int i = 0; i < face; ++i) {
2051 position += 1 + connectivity[position];
2063int Element::countPolygonVertices(
const long *connectivity)
2065 return connectivity[0];
2074int Element::countPolygonFaces(
const long *connectivity)
2076 return countPolygonVertices(connectivity);
2085int Element::countPolyhedronFaces(
const long *connectivity)
2087 return connectivity[0];
2099std::vector<ConstProxyVector<long>> Element::evalEdgeConnects(
int nRequestedEdges)
const
2101 if (nRequestedEdges == -1) {
2102 nRequestedEdges = getEdgeCount();
2104 assert(nRequestedEdges <= getEdgeCount());
2106 std::set<std::pair<long, long>> edgeSet;
2107 std::vector<ConstProxyVector<long>> edgeConnectStorage(nRequestedEdges, ConstProxyVector<long>(ConstProxyVector<long>::INTERNAL_STORAGE, 2));
2109 int nFaces = getFaceCount();
2110 for (
int i = 0; i < nFaces; ++i) {
2111 ConstProxyVector<long> faceVertexIds = getFaceVertexIds(i);
2112 int nFaceVertices = faceVertexIds.size();
2113 for (
int k = 0; k < nFaceVertices; ++k) {
2114 long vertex_A = faceVertexIds[k];
2115 long vertex_B = faceVertexIds[(k + 1) % nFaceVertices];
2116 if (vertex_A > vertex_B) {
2117 std::swap(vertex_A, vertex_B);
2120 std::pair<long, long> edgePair = std::pair<long, long>(vertex_A, vertex_B);
2121 std::pair<std::set<std::pair<long, long>>::iterator,
bool> insertResult = edgeSet.insert(edgePair);
2122 if (insertResult.second) {
2123 ConstProxyVector<long>::storage_pointer connectStorage = edgeConnectStorage[edgeSet.size() - 1].storedData();
2124 connectStorage[0] = edgePair.first;
2125 connectStorage[1] = edgePair.second;
2127 if (edgeSet.size() == (std::size_t) nRequestedEdges) {
2128 return edgeConnectStorage;
2134 assert((
int) edgeSet.size() == nRequestedEdges);
2136 return edgeConnectStorage;
2144unsigned int Element::getBinarySize()
const
2146 unsigned int binarySize =
sizeof(m_type) +
sizeof(m_id) + getConnectSize() *
sizeof(long) +
sizeof(m_pid);
2148 binarySize +=
sizeof(int);
The Tesselation class allows to tessalete polygons and polyhedrons.
The Element class provides an interface for defining elements.
double evalArea(const std::array< double, 3 > *coordinates) const
const long * getConnect() const
int getConnectSize() const
Metafunction for generating a pierced storage.
iterator find(const id_t &id) noexcept
Metafunction for generating a pierced vector.
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
void set(__PXV_POINTER__ data, std::size_t size)
The Reference1DElementInfo class allows to define information about reference one-dimensional element...
The Reference2DElementInfo class allows to define information about reference two-dimensional element...
The Reference3DElementInfo class allows to define information about reference three-dimensional eleme...
The ReferenceElementInfo class allows to define information about reference elements.
static bool hasInfo(ElementType type)
double norm2(const std::array< T, d > &x)
#define BITPIT_UNREACHABLE(str)
#define BITPIT_UNUSED(variable)
#define BITPIT_CREATE_WORKSPACE(workspace, item_type, size, stack_size)
Logger & operator<<(Logger &logger, LoggerManipulator< T > &&m)