25#include "bitpit_common.hpp"
26#include "bitpit_IO.hpp"
28#include "surfunstructured.hpp"
42#if BITPIT_ENABLE_MPI==1
56 :
SurfaceKernel(communicator, haloSize, ADAPTION_MANUAL, PARTITIONING_ENABLED)
67#if BITPIT_ENABLE_MPI==1
95#if BITPIT_ENABLE_MPI==1
111 :
SurfaceKernel(id, dimension, communicator, haloSize, ADAPTION_MANUAL, PARTITIONING_ENABLED)
125#if BITPIT_ENABLE_MPI==1
139 :
SurfaceKernel(communicator, haloSize, ADAPTION_MANUAL, PARTITIONING_ENABLED)
171 const int DUMP_VERSION = 5;
227 throw std::runtime_error (
"The function 'locatePoint' is not implemented yet");
229 return Cell::NULL_ID;
250 const long *adjacencies;
273 for (c_ =
cellBegin(); c_ != ce_; ++c_) {
275 n_faces = c_->getFaceCount();
277 for (i = 0; i < n_faces; ++i) {
279 n_adj = c_->getAdjacencyCount(i);
280 adjacencies = c_->getAdjacencies(i);
281 for (j = 0; j < n_adj; ++j) {
282 check = check && (
id > adjacencies[j]);
290 int faceConnectSize = faceConnect.
size();
292 std::unique_ptr<long[]> edgeConnect = std::unique_ptr<long[]>(
new long[faceConnectSize]);
293 for (
int k = 0; k < faceConnectSize; ++k) {
294 edgeConnect[k] = faceConnect[k];
298 net.
addCell(edgeType, std::move(edgeConnect));
330 int PIDOffset,
bool PIDSquash)
332 return importSTL(filename, STLReader::FormatUnknown,
false, PIDOffset, PIDSquash);
359 int PIDOffset,
bool PIDSquash,
360 std::unordered_map<int, std::string> *PIDNames)
362 STLReader::Format format;
364 format = STLReader::FormatBinary;
366 format = STLReader::FormatASCII;
369 return importSTL(filename, format,
false, PIDOffset, PIDSquash, PIDNames);
406 bool joinFacets,
int PIDOffset,
bool PIDSquash,
407 std::unordered_map<int, std::string> *PIDNames)
413 if (format == STLReader::FormatUnknown) {
419 if (readerError != 0) {
429 std::array<double, 3> *candidateVertexCoords;
430 Vertex::Less vertexLess(10 * std::numeric_limits<double>::epsilon());
432 auto vertexCoordsLess = [
this, &vertexLess, &candidateVertexCoords](
const long &id_1,
const long &id_2)
434 const std::array<double, 3> &coords_1 = (id_1 >= 0) ? this->
getVertex(id_1).
getCoords() : *candidateVertexCoords;
435 const std::array<double, 3> &coords_2 = (id_2 >= 0) ? this->
getVertex(id_2).
getCoords() : *candidateVertexCoords;
437 return vertexLess(coords_1, coords_2);
440 std::set<long,
decltype(vertexCoordsLess)> vertexCache(vertexCoordsLess);
452 readerError = reader.
readHeader(&name, &nFacets);
453 if (readerError != 0) {
454 if (readerError == -2) {
464 std::size_t nEstimatedVertices;
472 nEstimatedVertices =
static_cast<std::size_t
>(0.5 * nFacets) + 2;
474 nEstimatedVertices = nFacetVertices * nFacets;
480 for (std::size_t n = 0; n < nFacets; ++n) {
482 std::array<Vertex, 3> faceVertices;
483 std::array<double, 3> facetNormal;
484 readerError = reader.
readFacet(&(faceVertices[0].getCoords()), &(faceVertices[1].getCoords()), &(faceVertices[2].getCoords()), &facetNormal);
485 if (readerError != 0) {
490 std::unique_ptr<long[]> connectStorage = std::unique_ptr<long[]>(
new long[nFacetVertices]);
492 for (
int i = 0; i < nFacetVertices; ++i) {
504 candidateVertexCoords = &(faceVertices[i].getCoords());
507 auto vertexCacheItr = vertexCache.find(Vertex::NULL_ID);
508 if (vertexCacheItr == vertexCache.end()) {
510 vertexId = vertexItr.
getId();
511 vertexCache.insert(vertexId);
513 vertexId = *vertexCacheItr;
515 connectStorage[i] = vertexId;
518 for (
int i = 0; i < nFacetVertices; ++i) {
520 long vertexId = vertexItr.
getId();
521 connectStorage[i] = vertexId;
527 cellIterator->setPID(pid);
532 if (readerError != 0) {
538 if (PIDNames && !name.empty()) {
539 PIDNames->insert({{pid, name}});
545 if (format == STLReader::FormatBinary) {
551 readerError = reader.
readEnd();
552 if (readerError != 0) {
588 std::unordered_map<int, std::string> *PIDNames)
617 STLReader::Format format;
619 format = STLReader::FormatBinary;
621 format = STLReader::FormatASCII;
629 const std::string name =
"";
633#if BITPIT_ENABLE_MPI==1
635 isMasterWriter = (
getRank() == 0);
640 isMasterWriter =
true;
644 bool incrementalWrite;
645#if BITPIT_ENABLE_MPI==1
646 incrementalWrite =
true;
648 incrementalWrite =
false;
653#if BITPIT_ENABLE_MPI==1
655 MPI_Allreduce(MPI_IN_PLACE, &nFacets, 1, MPI_LONG, MPI_SUM,
getCommunicator());
660 if (isMasterWriter) {
662 writerError = writer.
writeBegin(STLWriter::WriteOverwrite, incrementalWrite);
663 if (writerError != 0) {
671 if (writerError != 0) {
677#if BITPIT_ENABLE_MPI==1
680 if (writerError != 0) {
687#if BITPIT_ENABLE_MPI==1
689 for (
int i = 0; i < nRanks; ++i) {
692 writerError = writer.
writeBegin(STLWriter::WriteAppend, incrementalWrite);
693 if (writerError != 0) {
706 const Cell &cell = *cellItr;
710 assert(cellVertexIds.
size() == 3);
720 writerError = writer.
writeFacet(coords_0, coords_1, coords_2, normal);
721 if (writerError != 0) {
727#if BITPIT_ENABLE_MPI==1
730 if (writerError != 0) {
742 if (isMasterWriter) {
743#if BITPIT_ENABLE_MPI==1
747 writerError = writer.
writeBegin(STLWriter::WriteAppend, incrementalWrite);
748 if (writerError != 0) {
756 if (writerError != 0) {
764 if (writerError != 0) {
787 STLWriter writer(filename, STLReader::FormatASCII);
791#if BITPIT_ENABLE_MPI==1
793 isMasterWriter = (
getRank() == 0);
798 isMasterWriter =
true;
802 bool incrementalWrite =
true;
804#if BITPIT_ENABLE_MPI==1
810 std::set<int> cellPIDs;
811#if BITPIT_ENABLE_MPI==1
814 std::vector<int> localPIDs(internalPIDs.begin(), internalPIDs.end());
815 int nLocalPids = localPIDs.size();
817 std::vector<int> gatherPIDCount(nRanks);
818 MPI_Allgather(&nLocalPids, 1, MPI_INT, gatherPIDCount.data(), 1, MPI_INT,
getCommunicator());
820 std::vector<int> gatherPIDDispls(nRanks, 0);
821 for (
int i = 1; i < nRanks; ++i) {
822 gatherPIDDispls[i] = gatherPIDDispls[i - 1] + gatherPIDCount[i - 1];
825 int gatherPIDsSize = gatherPIDDispls.back() + gatherPIDCount.back();
827 std::vector<int> globalPIDs(gatherPIDsSize);
828 MPI_Allgatherv(localPIDs.data(), nLocalPids, MPI_INT, globalPIDs.data(),
829 gatherPIDCount.data(), gatherPIDDispls.data(), MPI_INT,
getCommunicator());
831 cellPIDs = std::set<int>(globalPIDs.begin(), globalPIDs.end());
840 bool firstPID =
true;
841 for (
int pid : cellPIDs) {
846 long nFacets = cells.size();
847#if BITPIT_ENABLE_MPI==1
849 MPI_Allreduce(MPI_IN_PLACE, &nFacets, 1, MPI_LONG, MPI_SUM,
getCommunicator());
855 if (PIDNames && PIDNames->count(pid) > 0) {
856 name = PIDNames->at(pid);
858 name = std::to_string(pid);
862 if (isMasterWriter) {
864 STLWriter::WriteMode writeMode;
866 writeMode = STLWriter::WriteOverwrite;
868 writeMode = STLWriter::WriteAppend;
871 writerError = writer.
writeBegin(writeMode, incrementalWrite);
872 if (writerError != 0) {
880 if (writerError != 0) {
886#if BITPIT_ENABLE_MPI==1
889 if (writerError != 0) {
896#if BITPIT_ENABLE_MPI==1
897 for (
int i = 0; i < nRanks; ++i) {
900 writerError = writer.
writeBegin(STLWriter::WriteAppend, incrementalWrite);
901 if (writerError != 0) {
910 for (
long cellId : cells) {
916 assert(cellVertexIds.
size() == 3);
926 writerError = writer.
writeFacet(coords_0, coords_1, coords_2, normal);
927 if (writerError != 0) {
933 #if BITPIT_ENABLE_MPI==1
936 if (writerError != 0) {
948 if (isMasterWriter) {
949#if BITPIT_ENABLE_MPI==1
953 writerError = writer.
writeBegin(STLWriter::WriteAppend, incrementalWrite);
954 if (writerError != 0) {
962 if (writerError != 0) {
970 if (writerError != 0) {
1001 return importDGF(filename,
false, PIDOffset, PIDSquash);
1038 std::vector<std::array<double, 3>> vertex_list;
1039 std::vector<std::vector<int>> simplex_list;
1040 std::vector<int> simplex_PID;
1041 std::vector<long> vertex_map;
1042 std::vector<long> connect;
1045 std::vector<std::vector<int>>::iterator c_, ce_;
1046 std::vector<int>::iterator i_, ie_;
1047 std::vector<long>::iterator j_, je_;
1054 dgf_in.
load(nV, nS, vertex_list, simplex_list, simplex_PID);
1057 vertex_map.resize(nV);
1066 Vertex::Less vertexLess(10 * std::numeric_limits<double>::epsilon());
1068 auto vertexCoordsLess = [&vertexLess, &vertex_list](
const int &i,
const int &j)
1070 return vertexLess(vertex_list[i], vertex_list[j]);
1073 std::set<int,
decltype(vertexCoordsLess)> vertexCache(vertexCoordsLess);
1075 for (
int i = 0; i < nV; ++i) {
1077 auto vertexCacheItr = vertexCache.find(i);
1078 if (vertexCacheItr == vertexCache.end()) {
1080 vertexId = vertexItr.
getId();
1081 vertexCache.insert(i);
1083 vertexId = vertex_map[*vertexCacheItr];
1085 vertex_map[i] = vertexId;
1088 for (
int i = 0; i < nV; ++i) {
1090 long vertexId = vertexItr.
getId();
1091 vertex_map[i] = vertexId;
1096 ce_ = simplex_list.end();
1097 for (c_ = simplex_list.begin(); c_ != ce_; ++c_) {
1099 for (i_ = c_->begin(); i_ != ie_; ++i_) {
1100 *i_ = vertex_map[*i_];
1106 for (c_ = simplex_list.begin(), k = 0; c_ != ce_; ++c_, ++k) {
1109 connect.resize(c_->size(), Vertex::NULL_ID);
1110 je_ = connect.end();
1111 for (j_ = connect.begin(); j_ != je_; ++j_) {
1118 int cellPID = PIDOffset;
1120 cellPID += simplex_PID[k];
1123 cellIterator->setPID(cellPID);
1146 long vcount, ccount, idx;
1147 std::vector<std::array<double, 3>> vertex_list(nV);
1148 std::vector<std::vector<int>> simplex_list(nS);
1149 std::unordered_map<long, long> vertex_map;
1164 vertex_list[vcount] = v_->getCoords();
1165 vertex_map[idx] = vcount;
1172 for (c_ =
cellBegin(); c_ != ce_; ++c_) {
1174 nv = cellVertexIds.
size();
1175 simplex_list[ccount].resize(nv);
1176 for (v = 0; v < nv; ++v) {
1177 simplex_list[ccount][v] = vertex_map[cellVertexIds[v]];
1183 dgf_in.
save(nV, nS, vertex_list, simplex_list);
1197 switch(nFacetVertices) {
1200 return ElementType::VERTEX;
1203 return ElementType::LINE;
1206 return ElementType::TRIANGLE;
1209 return ElementType::QUAD;
1212 return ElementType::UNDEFINED;
The Cell class defines the cells.
Interface to DGF I/O function.
void save(int &, int &, std::vector< std::vector< double > > &, std::vector< std::vector< int > > &)
void load(int &, int &, std::vector< std::vector< double > > &, std::vector< std::vector< int > > &)
static ConstProxyVector< long > getVertexIds(ElementType type, const long *connectivity)
The LineUnstructured class defines an unstructured line tasselation.
VertexIterator vertexEnd()
void dumpInterfaces(std::ostream &stream) const
CellConstIterator internalCellConstEnd() const
std::vector< long > getInternalCellsByPID(int pid)
void dumpVertices(std::ostream &stream) const
void dumpCells(std::ostream &stream) const
CellConstIterator internalCellConstBegin() const
VertexIterator vertexBegin()
virtual long getVertexCount() const
void restoreCells(std::istream &stream)
VertexIterator addVertex(const Vertex &source, long id=Vertex::NULL_ID)
CellIterator addCell(const Cell &source, long id=Element::NULL_ID)
void restoreVertices(std::istream &stream)
const MPI_Comm & getCommunicator() const
void restore(std::istream &stream, bool reregister=false)
bool isPartitioned() const
Vertex & getVertex(long id)
std::set< int > getInternalCellPIDs()
void restoreInterfaces(std::istream &stream)
virtual long getCellCount() const
long getInternalCellCount() const
int getProcessorCount() const
bool reserveCells(size_t nCells)
bool reserveVertices(size_t nVertices)
The PatchManager oversee the handling of the patches.
id_t getId(const id_t &fallback=-1) const noexcept
Iterator for the class PiercedStorage.
Metafunction for generating a list of elements that can be either stored in an external vectror or,...
static BITPIT_PUBLIC_API const ReferenceElementInfo & getInfo(ElementType type)
Class for reading ASCII and binary STL files.
int readFacet(std::array< double, 3 > *V0, std::array< double, 3 > *V1, std::array< double, 3 > *V2, std::array< double, 3 > *N)
int readHeader(std::string *name, std::size_t *nT)
Class for writing ASCII and binary STL files.
int writeFacet(const std::array< double, 3 > &V0, const std::array< double, 3 > &V1, const std::array< double, 3 > &V2, const std::array< double, 3 > &N)
int writeFooter(const std::string &name)
int writeHeader(const std::string &name, std::size_t nT)
int writeBegin(WriteMode writeMode, bool partialWrite=false)
The SurfUnstructured class defines an unstructured surface triangulation.
void _dump(std::ostream &stream) const override
int importDGF(const std::string &filename, int PIDOffset=0, bool PIDSquash=false)
SurfUnstructured(MPI_Comm communicator, std::size_t haloSize=1)
void extractEdgeNetwork(LineUnstructured &net)
int exportSTL(const std::string &filename, bool isBinary)
long locatePoint(const std::array< double, 3 > &point) const override
std::unique_ptr< PatchKernel > clone() const override
int _getDumpVersion() const override
int importSTL(const std::string &filename, int PIDOffset=0, bool PIDSquash=false)
void _restore(std::istream &stream) override
int exportSTLSingle(const std::string &name, bool isBinary)
static ElementType getDGFFacetType(int nFacetVertices)
int exportSTLMulti(const std::string &name, std::unordered_map< int, std::string > *PIDNames=nullptr)
int exportDGF(const std::string &filename)
The SurfaceKernel class provides an interface for defining surface patches.
virtual std::array< double, 3 > evalFacetNormal(long, const std::array< double, 3 > &orientation={{0., 0., 1.}}) const
std::array< double, 3 > & getCoords()
#define BITPIT_UNUSED(variable)