25 #include "RefineGeometry.hpp"
27 #include "mimmo_parallel.hpp"
36 m_name =
"mimmo.RefineGeometry";
48 std::string fallback_name =
"ClassNONE";
49 std::string input_name = rootXML.get(
"ClassName", fallback_name);
50 input_name = bitpit::utils::string::trim(input_name);
52 m_name =
"mimmo.RefineGeometry";
57 if(input_name ==
"mimmo.RefineGeometry"){
93 std::swap(m_type,x.m_type);
94 std::swap(m_steps,x.m_steps);
95 std::swap(m_refinements,x.m_refinements);
128 throw std::runtime_error(
m_name +
" : refinement method not allowed");
138 if (type != 0 && type != 1)
139 throw std::runtime_error(
m_name +
" : refinement method not allowed");
180 (*m_log)<<
m_name +
" : no geometry to refine found"<<std::endl;
185 (*m_log)<<
m_name +
" : data structure type different from Surface "<<std::endl;
186 throw std::runtime_error (
m_name +
" : data structure type different from Surface");
192 (*m_log)<<
m_name +
" : detected not regular triangulated surface, no redgreen refinement can be performed. Returning. "<<std::endl;
224 if(slotXML.hasOption(
"RefineType")){
225 std::string input = slotXML.get(
"RefineType");
226 input = bitpit::utils::string::trim(input);
229 std::stringstream ss(input);
235 if(slotXML.hasOption(
"RefineSteps")){
236 std::string input = slotXML.get(
"RefineSteps");
237 input = bitpit::utils::string::trim(input);
240 std::stringstream ss(input);
246 if(slotXML.hasOption(
"SmoothingSteps")){
247 std::string input = slotXML.get(
"SmoothingSteps");
248 input = bitpit::utils::string::trim(input);
251 std::stringstream ss(input);
269 slotXML.set(
"RefineType", std::to_string(
int(
m_type)));
271 slotXML.set(
"SmoothingSteps", std::to_string(
m_steps));
300 (*m_log)<<
"WARNING " <<
m_name <<
" : uniqueness of cell/vertex ids among processes is not maintained during parallel geometry refinement."<<std::endl;
305 std::unordered_set<long> newCells;
306 std::unordered_set<long> toDelete;
311 std::array<double,3> centroid =
getGeometry()->evalCellCentroid(cellId);
315 std::vector<bitpit::Vertex> perimeter;
316 for (
const long &
id :
getGeometry()->getPatch()->getCell(cellId).getVertexIds()){
317 perimeter.emplace_back(
getGeometry()->getPatch()->getVertex(
id));
321 std::vector<long> generatedCells =
ternaryRefineCell(cellId, perimeter, centroid);
324 if (!generatedCells.empty()){
327 toDelete.insert(cellId);
330 if (coarsepatch !=
nullptr)
332 bitpit::Cell & cell =
getGeometry()->getPatch()->getCell(cellId);
333 coarsepatch->addCell(cell, cellId);
334 for (
long vertexId : cell.getVertexIds()){
335 bitpit::Vertex vertex =
getGeometry()->getPatch()->getVertex(vertexId);
336 coarsepatch->addVertex(vertex, vertexId);
341 for (
long newCellId : generatedCells){
342 if (mapping !=
nullptr)
343 mapping->insert({newCellId, cellId});
344 newCells.insert(newCellId);
369 if (coarsepatch !=
nullptr){
370 coarsepatch->update();
375 if (refinepatch !=
nullptr){
376 for (
long newcellId : newCells){
377 bitpit::Cell & cell =
getGeometry()->getPatch()->getCell(newcellId);
378 refinepatch->addCell(cell, newcellId);
379 for (
long vertexId : cell.getVertexIds()){
380 const bitpit::Vertex & vertex =
getGeometry()->getPatch()->getVertex(vertexId);
381 refinepatch->addVertex(vertex, vertexId);
387 refinepatch->update();
390 refinepatch->deleteOrphanGhostCells();
391 refinepatch->getPatch()->deleteOrphanVertices();
395 refinepatch->update();
417 std::vector<long> newCellIDs;
419 bitpit::ElementType eletri = bitpit::ElementType::TRIANGLE;
423 const bitpit::Cell & cell =
getGeometry()->getPatch()->getCell(cellId);
425 long pid = cell.getPID();
429 std::size_t nnewTri = vertices.size();
430 newCellIDs.reserve(nnewTri);
436 for(std::size_t i=0; i<nnewTri; ++i){
437 connTriangle[0] = newVertID;
438 connTriangle[1] = vertices[ std::size_t( i % nnewTri) ].getId();
439 connTriangle[2] = vertices[ std::size_t( (i+1) % nnewTri ) ].getId();
442 rank =
getGeometry()->getPatch()->getCellRank(cellId);
444 newCellIDs.push_back(
getGeometry()->addConnectedCell(connTriangle, eletri, pid, bitpit::Cell::NULL_ID, rank));
470 (*m_log)<<
"WARNING " <<
m_name <<
" : uniqueness of cell/vertex ids among processes is not maintained during parallel geometry refinement."<<std::endl;
475 std::unordered_set<long> newCells;
476 std::unordered_set<long> toDelete;
479 std::unordered_map<long, int> refinementTag;
480 for(
const long cellId : geometry->getCellsIds()){
481 refinementTag[cellId] = 0;
486 std::set<long> edges;
489 std::unordered_map<long,long> edgeVertexId;
492 std::unordered_map<long,int> greenSplitFaceIndex;
496 geometry->updateAdjacencies();
497 geometry->updateInterfaces();
500 std::deque<long> newreds;
502 refinementTag[cellId] = 2;
503 newreds.push_back(cellId);
520 for (
auto & source_tuple : geometry->getPatch()->getGhostCellExchangeSources()){
522 for (
long id : source_tuple.second){
523 if (!refinementTagCommunicated.exists(
id)){
524 refinementTagCommunicated.insert(
id,-1);
525 greenSplitFaceIndexCommunicated.insert(
id,-1);
529 for (
auto & target_tuple : geometry->getPatch()->getGhostCellExchangeTargets()){
531 for (
long id : target_tuple.second){
533 if (!refinementTagCommunicated.exists(
id)){
534 refinementTagCommunicated.insert(
id, -1);
535 greenSplitFaceIndexCommunicated.insert(
id, -1);
544 bool check = newreds.empty();
549 bool global_check =
false;
551 while (!global_check){
560 long redId = newreds.front();
563 bitpit::Cell & redCell = geometry->getPatch()->getCell(redId);
566 if (redCell.getType() == bitpit::ElementType::TRIANGLE){
568 for (
int iface = 0; iface < 3; iface++){
570 if (!redCell.isFaceBorder(iface)){
573 int neighscount = redCell.getAdjacencyCount(iface);
574 const long * neighs = redCell.getAdjacencies(iface);
576 for (
int ineigh = 0; ineigh < neighscount; ineigh++){
578 long neighId = neighs[ineigh];
581 refinementTag[neighId]++;
586 long interfaceId = geometry->getPatch()->getCell(redId).getInterface(iface);
587 bitpit::Interface &
interface = geometry->getPatch()->getInterface(interfaceId);
588 edges.insert(interfaceId);
590 if (refinementTag[neighId] > 2){
595 if (refinementTag[neighId] == 2){
598 newreds.push_back(neighId);
601 greenSplitFaceIndex.erase(neighId);
604 else if (refinementTag[neighId] == 1){
607 bool isOwner = (interface.getOwner() == neighId);
612 splitface = interface.getOwnerFace();
615 splitface = interface.getNeighFace();
617 greenSplitFaceIndex[neighId] = splitface;
626 long interfaceId = redCell.getInterface(iface);
627 edges.insert(interfaceId);
635 check = newreds.empty();
641 global_check = check;
643 if (geometry->isParallel()){
648 for (
auto & source_tuple : geometry->getPatch()->getGhostCellExchangeSources()){
650 for (
long id : source_tuple.second){
651 refinementTagCommunicated.at(
id) = refinementTag.at(
id);
652 if (greenSplitFaceIndex.count(
id)){
653 greenSplitFaceIndexCommunicated.at(
id) = greenSplitFaceIndex.at(
id);
656 greenSplitFaceIndexCommunicated.at(
id) = -1;
660 for (
auto & target_tuple : geometry->getPatch()->getGhostCellExchangeTargets()){
662 for (
long id : target_tuple.second){
664 refinementTagCommunicated.at(
id) = -1;
665 greenSplitFaceIndexCommunicated.at(
id) = -1;
670 refinementTagCommunicated.communicateData();
671 greenSplitFaceIndexCommunicated.communicateData();
674 for (
auto ghostIt = geometry->getPatch()->ghostCellConstBegin(); ghostIt != geometry->getPatch()->ghostCellConstEnd(); ghostIt++){
675 long ghostId = ghostIt->getId();
678 refinementTagCommunicated[ghostId] = std::min(2, refinementTagCommunicated[ghostId]);
681 if (refinementTagCommunicated[ghostId] > refinementTag[ghostId]){
682 refinementTag[ghostId] = refinementTagCommunicated[ghostId];
684 if (refinementTag[ghostId] == 1){
686 greenSplitFaceIndex[ghostId] = greenSplitFaceIndexCommunicated[ghostId];
688 else if (refinementTag[ghostId] >= 2){
690 newreds.push_back(ghostId);
692 greenSplitFaceIndex.erase(ghostId);
698 global_check = newreds.empty();
699 MPI_Allreduce(MPI_IN_PLACE, &global_check, 1, MPI_C_BOOL, MPI_LAND, m_communicator);
708 for (
long interfaceId : edges){
710 bitpit::ConstProxyVector<long> vertexIds = geometry->getPatch()->getInterface(interfaceId).getVertexIds();
711 std::array<double,3> newCoordinates({0.,0.,0.});
712 for (
long vertexId : vertexIds){
713 newCoordinates += geometry->getVertexCoords(vertexId);
715 newCoordinates /= double(vertexIds.size());
716 long newVertexId = geometry->addVertex(newCoordinates);
717 edgeVertexId[interfaceId] = newVertexId;
721 for (
auto & tupletag : refinementTag){
723 long cellId = tupletag.first;
724 int tag = std::min(2, tupletag.second);
730 std::vector<long> generatedCells;
735 bitpit::Cell & cell = geometry->getPatch()->getCell(cellId);
739 std::vector<long> newCellVertexIds(cell.getFaceCount());
740 for (
int iface=0; iface<cell.getFaceCount(); iface++){
741 long interfaceId = cell.getInterface(iface);
742 newCellVertexIds[iface] = edgeVertexId.at(interfaceId);
750 bitpit::Cell & cell = geometry->getPatch()->getCell(cellId);
754 int splitFaceIndex = greenSplitFaceIndex.at(cellId);
755 long interfaceId = cell.getInterface(splitFaceIndex);
756 long newCellVertexId = edgeVertexId.at(interfaceId);
758 generatedCells =
greenRefineCell(cellId, newCellVertexId, splitFaceIndex);
761 if (!generatedCells.empty()){
764 toDelete.insert(cellId);
767 if (coarsepatch !=
nullptr)
772 bitpit::Cell & cell = geometry->getPatch()->getCell(cellId);
774 coarsepatch->addCell(cell, cellId);
775 for (
long vertexId : cell.getVertexIds()){
776 bitpit::Vertex & vertex = geometry->getPatch()->getVertex(vertexId);
777 coarsepatch->addVertex(vertex, vertexId);
782 for (
long newCellId : generatedCells){
783 if (mapping !=
nullptr){
784 mapping->insert({newCellId, cellId});
786 newCells.insert(newCellId);
805 if (refinepatch !=
nullptr){
806 for (
long newcellId : newCells){
807 bitpit::Cell & cell =
getGeometry()->getPatch()->getCell(newcellId);
808 refinepatch->addCell(cell, newcellId);
809 for (
long vertexId : cell.getVertexIds()){
810 bitpit::Vertex & vertex =
getGeometry()->getPatch()->getVertex(vertexId);
811 refinepatch->addVertex(vertex, vertexId);
824 if (coarsepatch !=
nullptr){
825 coarsepatch->update();
829 if (refinepatch !=
nullptr){
832 refinepatch->deleteOrphanGhostCells();
833 refinepatch->getPatch()->deleteOrphanVertices();
836 refinepatch->update();
853 std::vector<long> newCellIDs;
855 bitpit::ElementType eletype;
856 bitpit::ElementType eletri = bitpit::ElementType::TRIANGLE;
860 bitpit::Cell cell =
getGeometry()->getPatch()->getCell(cellId);
862 eletype = cell.getType();
864 if (eletype != eletri){
865 (*m_log)<<
m_name +
" : red refinement allowd only for triangles. Skip element."<<std::endl;
869 long pid = cell.getPID();
873 rank =
getGeometry()->getPatch()->getCellRank(cellId);
877 std::size_t sizeEle = 3;
878 newCellIDs.reserve(sizeEle+1);
883 connTriangle[0] = newVertexIds[0];
884 connTriangle[1] = newVertexIds[1];
885 connTriangle[2] = newVertexIds[2];
886 newCellIDs.push_back(
getGeometry()->addConnectedCell(connTriangle, eletri, pid, bitpit::Cell::NULL_ID, rank));
890 for(std::size_t i=0; i<sizeEle; ++i){
891 connTriangle[0] = cell.getVertexId(
int( (i+1) % sizeEle) );
892 connTriangle[1] = newVertexIds[ std::size_t( (i+1) % sizeEle) ];
893 connTriangle[2] = newVertexIds[ std::size_t( (i) % sizeEle ) ];
894 newCellIDs.emplace_back(
getGeometry()->addConnectedCell(connTriangle, eletri, pid, bitpit::Cell::NULL_ID, rank));
911 std::vector<long> newCellIDs;
913 bitpit::ElementType eletype;
914 bitpit::ElementType eletri = bitpit::ElementType::TRIANGLE;
918 bitpit::Cell cell =
getGeometry()->getPatch()->getCell(cellId);
920 eletype = cell.getType();
922 if (eletype != eletri){
923 (*m_log)<<
m_name +
" : red refinement allowd only for triangles. Skip element."<<std::endl;
927 long pid = cell.getPID();
931 rank =
getGeometry()->getPatch()->getCellRank(cellId);
935 std::size_t sizeEle = 3;
936 newCellIDs.reserve(sizeEle-1);
940 for(std::size_t i=0; i<sizeEle-1; ++i){
941 connTriangle[0] = newVertexId;
942 connTriangle[1] = cell.getVertexId(
int( (splitEdgeIndex+1+i) % sizeEle) );
943 connTriangle[2] = cell.getVertexId(
int( (splitEdgeIndex+2+i) % sizeEle) );
944 newCellIDs.emplace_back(
getGeometry()->addConnectedCell(connTriangle, eletri, pid, bitpit::Cell::NULL_ID, rank));
966 geometry->updateAdjacencies();
969 geometry->updateInterfaces();
972 geometry->buildPatchInfo();
975 geometry->buildPointConnectivity();
980 geometry->updatePointGhostExchangeInfo();
986 for (
auto source_tuple : geometry->getPointGhostExchangeSources()){
988 for (
long id : source_tuple.second){
989 if (!newCoordinatesCommunicated.exists(
id)){
990 newCoordinatesCommunicated.insert(
id, std::array<double,3>({{0.,0.,0.}}));
994 for (
auto target_tuple : geometry->getPointGhostExchangeTargets()){
996 for (
long id : target_tuple.second){
997 if (!newCoordinatesCommunicated.exists(
id)){
998 newCoordinatesCommunicated.insert(
id, std::array<double,3>({{0.,0.,0.}}));
1006 double lambda = 0.6;
1007 double kappa = -0.603*lambda;
1009 for (
int istep=0; istep <
m_steps; istep++){
1013 std::unordered_map<long, std::array<double,3>> newcoordinates;
1014 std::unordered_set<long> pointconnectivity;
1015 std::array<double,3> newcoords, oldcoords, neighcoords;
1016 double weight, sumweights;
1017 newcoordinates.reserve(geometry->getNVertices());
1020 for (
const bitpit::Vertex & vert : geometry->getVertices()){
1021 long id = vert.getId();
1023 if (geometry->isPointInterior(
id)){
1025 oldcoords = geometry->getVertexCoords(
id);
1026 newcoords = std::array<double,3>{{0.,0.,0.}};
1029 if (constrainedVertices ==
nullptr || !constrainedVertices->count(
id)){
1030 pointconnectivity = geometry->getPointConnectivity(
id);
1032 for (
long idneigh : pointconnectivity){
1033 neighcoords = geometry->getVertexCoords(idneigh);
1034 std::array<double,3> distancevector = (neighcoords-oldcoords);
1036 sumweights += weight;
1037 newcoords += lambda*weight*distancevector;
1039 if (sumweights > 0.)
1040 newcoords /= sumweights;
1043 newcoords += oldcoords;
1044 newcoordinates[id] = newcoords;
1049 #if MIMMO_ENABLE_MPI
1051 if (geometry->isParallel()){
1056 for (
auto source_tuple : geometry->getPointGhostExchangeSources()){
1058 for (
long id : source_tuple.second){
1059 newCoordinatesCommunicated.at(
id) = newcoordinates.at(
id);
1064 newCoordinatesCommunicated.communicateData();
1067 for (
auto target_tuple : geometry->getPointGhostExchangeTargets()){
1069 for (
long id : target_tuple.second){
1070 newcoordinates[id] = newCoordinatesCommunicated.at(
id);
1079 for (
const bitpit::Vertex & vert : geometry->getVertices()){
1080 long id = vert.getId();
1081 geometry->modifyVertex(newcoordinates[
id],
id);
1091 std::unordered_map<long, std::array<double,3>> newcoordinates;
1092 std::unordered_set<long> pointconnectivity;
1093 std::array<double,3> newcoords, oldcoords, neighcoords;
1094 double weight, sumweights;
1095 newcoordinates.reserve(geometry->getNVertices());
1098 for (
const bitpit::Vertex & vert : geometry->getVertices()){
1099 long id = vert.getId();
1100 oldcoords = geometry->getVertexCoords(
id);
1101 newcoords = std::array<double,3>{{0.,0.,0.}};
1104 if (constrainedVertices !=
nullptr && !constrainedVertices->count(
id)){
1105 pointconnectivity = geometry->getPointConnectivity(
id);
1107 for (
long idneigh : pointconnectivity){
1108 neighcoords = geometry->getVertexCoords(idneigh);
1110 sumweights += weight;
1111 newcoords += kappa*weight*(neighcoords-oldcoords);
1113 if (sumweights > 0.)
1114 newcoords /= sumweights;
1117 newcoords += oldcoords;
1118 newcoordinates[id] = newcoords;
1121 #if MIMMO_ENABLE_MPI
1123 if (geometry->isParallel()){
1129 for (
auto source_tuple : geometry->getPointGhostExchangeSources()){
1131 for (
long id : source_tuple.second){
1132 newCoordinatesCommunicated.at(
id) = newcoordinates.at(
id);
1137 newCoordinatesCommunicated.communicateData();
1140 for (
auto target_tuple : geometry->getPointGhostExchangeTargets()){
1141 for (
long id : target_tuple.second){
1142 newcoordinates.at(
id) = newCoordinatesCommunicated.at(
id);
1151 for (
const bitpit::Vertex & vert : geometry->getVertices()){
1152 long id = vert.getId();
1153 geometry->modifyVertex(newcoordinates[
id],
id);
1174 for (
const bitpit::Cell & cell :
getGeometry()->getCells()){
1175 check = check && (cell.getType() == bitpit::ElementType::TRIANGLE);
1177 #if MIMMO_ENABLE_MPI
1178 MPI_Allreduce(MPI_IN_PLACE, &check, 1, MPI_C_BOOL, MPI_LAND, m_communicator);