Loading...
Searching...
No Matches
levelSetMaskObject.cpp
1/*---------------------------------------------------------------------------*\
2 *
3 * bitpit
4 *
5 * Copyright (C) 2015-2021 OPTIMAD engineering Srl
6 *
7 * -------------------------------------------------------------------------
8 * License
9 * This file is part of bitpit.
10 *
11 * bitpit is free software: you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License v3 (LGPL)
13 * as published by the Free Software Foundation.
14 *
15 * bitpit is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with bitpit. If not, see <http://www.gnu.org/licenses/>.
22 *
23\*---------------------------------------------------------------------------*/
24
25# include "levelSetMaskObject.hpp"
26
27namespace bitpit {
28
41LevelSetMaskObject::LevelSetMaskObject(int id, const std::unordered_set<long> &mask, const VolumeKernel &mesh )
43
44 std::unordered_map<long,long> meshToEnvelope ;
45
46 std::unique_ptr<SurfUnstructured> segmentation = extractCellEnvelope(mask,mesh,meshToEnvelope) ;
47
48 long intrIndex = meshToEnvelope.begin()->first;
49 long enveIndex = meshToEnvelope.begin()->second;
50
51 bool sameOrientation = sameInterfaceEnvelopeOrientation(mesh, intrIndex, *segmentation, enveIndex);
52
53 auto const &interface = mesh.getInterface(intrIndex);
54 long ownerId = interface.getOwner();
55 bool invert = (mask.count(ownerId)==0) ;
56
57 bool flip = (sameOrientation == invert);
58
59 bool orientable = segmentation->adjustCellOrientation( enveIndex, flip);
60 if( !orientable){
61 throw std::runtime_error ("Error in LevelSetMaskObject");
62 }
63
64 this->setSurface(std::move(segmentation));
65}
66
75LevelSetMaskObject::LevelSetMaskObject(int id, const std::vector<long> &list, long interfaceId, bool invert, const VolumeKernel &mesh )
77
78 std::unordered_map<long,long> meshToEnvelope ;
79
80 std::unique_ptr<SurfUnstructured> segmentation = extractFaceEnvelope(list,mesh,meshToEnvelope) ;
81
82 long enveIndex = meshToEnvelope.at(interfaceId);
83 bool sameOrientation = sameInterfaceEnvelopeOrientation(mesh, interfaceId, *segmentation, enveIndex);
84
85 bool flip = (sameOrientation == invert);
86
87 bool orientable = segmentation->adjustCellOrientation( enveIndex, flip);
88 if( !orientable){
89 throw std::runtime_error ("Error in LevelSetMaskObject");
90 }
91
92 this->setSurface(std::move(segmentation));
93}
94
104std::unique_ptr<SurfUnstructured> LevelSetMaskObject::extractCellEnvelope(const std::unordered_set<long> &mask, const VolumeKernel &mesh, std::unordered_map<long,long> &meshToEnvelope){
105
106 std::vector<long> list;
107
108 for( long cellIndex : mask){
109 const auto &cell = mesh.getCell(cellIndex);
110 const long *adjacencies = cell.getAdjacencies();
111 const long *interfaceIndex = cell.getInterfaces();
112
113 int interfaceCount= cell.getInterfaceCount() ;
114
115 for(int i=0; i<interfaceCount; i++){
116 long neigh = adjacencies[i];
117
118 if(mask.count(neigh)==0){
119 list.push_back(interfaceIndex[i]);
120 }
121 }
122 }
123
124 return extractFaceEnvelope(list,mesh,meshToEnvelope);
125}
126
135std::unique_ptr<SurfUnstructured> LevelSetMaskObject::extractFaceEnvelope(const std::vector<long> &list, const VolumeKernel &mesh, std::unordered_map<long,long> &meshToEnvelope){
136
137 std::unique_ptr<SurfUnstructured> envelope;
138#if BITPIT_ENABLE_MPI==1
139 envelope = std::unique_ptr<SurfUnstructured>(new SurfUnstructured(mesh.getDimension()-1,mesh.getCommunicator()));
140#else
141 envelope = std::unique_ptr<SurfUnstructured>(new SurfUnstructured(mesh.getDimension()-1));
142#endif
143
144 // ====================================================================== //
145 // RESIZE DATA STRUCTURES //
146 // ====================================================================== //
147 long nVertices(0);
148 long nCells(list.size());
149
150 for( long faceIndex : list){
151 auto const &interface = mesh.getInterface(faceIndex);
152 nVertices += interface.getVertexCount() ;
153 }
154
155 envelope->reserveVertices(nVertices);
156 envelope->reserveCells(nCells);
157
158 // ====================================================================== //
159 // LOOP OVER CELLS //
160 // ====================================================================== //
161 std::unordered_map<long,long> vertexMap;
162
163 for( long faceIndex : list){
164 auto const &interface = mesh.getInterface(faceIndex);
165 ConstProxyVector<long> faceVertexIds = interface.getVertexIds();
166 int nFaceVertices = faceVertexIds.size();
167
168 // Add face vertices to the envelope and get face
169 // connectivity in the envelope
170 std::unique_ptr<long[]> faceEnvelopeConnect = std::unique_ptr<long[]>(new long[nFaceVertices]);
171 for (int j = 0; j < nFaceVertices; ++j) {
172 long vertexId = faceVertexIds[j];
173
174 // If the vertex is not yet in the envelope
175 // add it.
176 if (vertexMap.count(vertexId) == 0) {
177 const Vertex &vertex = mesh.getVertex(vertexId);
178 auto envelopeVertex = envelope->addVertex(vertex);
179 vertexMap[vertexId] = envelopeVertex->getId();
180 }
181
182 // Update face connectivity in the envelope
183 faceEnvelopeConnect[j] = vertexMap.at(vertexId);
184 }
185
186 // Add face to envelope
187 ElementType faceType = interface.getType();
188 PatchKernel::CellIterator cellItr = envelope->addCell(faceType, std::move(faceEnvelopeConnect));
189 meshToEnvelope.insert({{faceIndex,cellItr.getId()}});
190 }
191
192 envelope->squeeze();
193 envelope->initializeAdjacencies();
194 envelope->initializeInterfaces();
195
196 envelope->getVTK().setName("geometry_002") ;
197 envelope->write() ;
198
199 return envelope;
200
201}
202
211bool LevelSetMaskObject::sameInterfaceEnvelopeOrientation(const VolumeKernel &mesh, long faceIndex, SurfUnstructured &envelope, long enveIndex){
212
213 std::array<double,3> facetNormal = envelope.evalFacetNormal(enveIndex);
214 std::array<double,3> interfaceNormal = mesh.evalInterfaceNormal(faceIndex);
215
216 return (dotProduct(facetNormal,interfaceNormal)>0) ;
217
218}
219
220}
221
const long * getAdjacencies() const
Definition cell.cpp:841
LevelSetMaskObject(int, const std::unordered_set< long > &, const VolumeKernel &)
Implements visitor pattern fo segmentated geometries.
void setSurface(std::unique_ptr< const SurfUnstructured > &&surface, bool force=false)
Cell & getCell(long id)
The VolumeKernel class provides an interface for defining volume patches.
T dotProduct(const std::array< T, d > &x, const std::array< T, d > &y)
--- layout: doxygen_footer ---