Loading...
Searching...
No Matches
levelSetKernel.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 "levelSetKernel.hpp"
26
27# include "bitpit_CG.hpp"
28
29namespace bitpit {
30
41 m_mesh = NULL ;
43
44#if BITPIT_ENABLE_MPI
45 m_communicator = MPI_COMM_NULL;
46# endif
47
48}
49
56 m_mesh = patch ;
57 m_expectedFillIn = expectedFillIn ;
58
59#if BITPIT_ENABLE_MPI
60 // Initialize the communicator
61 if (m_mesh->isPartitioned()) {
62 initializeCommunicator();
63 }
64#endif
65}
66
71 m_mesh = NULL ;
72
73# if BITPIT_ENABLE_MPI
74 freeCommunicator();
75# endif
76
77}
78
84 return m_mesh ;
85}
86
96
103{
104 return m_mesh->getTol();
105}
106
113bool LevelSetKernel::update( const std::vector<adaption::Info> &adaptionData ) {
114
115 // Early return if the kernel doesn't need to be updated
116#if BITPIT_ENABLE_MPI
117 VolumeKernel *mesh = getMesh();
118 bool isMeshPartitioned = mesh->isPartitioned();
119#endif
120
121 // Check if the levelset needs to be updated
122 bool isDirty = false;
123 for( const adaption::Info &adaptionInfo : adaptionData){
124 if( adaptionInfo.entity != adaption::Entity::ENTITY_CELL){
125 continue;
126 }
127
128 isDirty = true;
129 break;
130 }
131
132#if BITPIT_ENABLE_MPI
133 if (isMeshPartitioned) {
134 MPI_Allreduce(MPI_IN_PLACE, &isDirty, 1, MPI_C_BOOL, MPI_LOR, getCommunicator());
135 }
136#endif
137
138 // Early return if no changes were detected
139 if (!isDirty) {
140 return false;
141 }
142
143#if BITPIT_ENABLE_MPI
144 // Set the communicator
145 //
146 // The mesh may have been partitioned after being set.
148 initializeCommunicator();
149 }
150#endif
151
152 // The kernel has been updated
153 return true;
154}
155
164bool LevelSetKernel::intersectCellPlane( long id, const std::array<double,3> &root, const std::array<double,3> &normal, double tolerance ) {
165
166 std::array<double,3> minPoint;
167 std::array<double,3> maxPoint;
168 m_mesh->evalCellBoundingBox(id, &minPoint, &maxPoint);
169
170 int dim = m_mesh->getDimension();
171 return CGElem::intersectPlaneBox( root, normal, minPoint, maxPoint, dim, tolerance);
172}
173
180bool LevelSetKernel::isPointInCell(long id, const std::array<double,3> &pointCoords) const {
181 return m_mesh->isPointInside(id,pointCoords);
182}
183
192double LevelSetKernel::isCellInsideBoundingBox( long id, const std::array<double, 3> &boxMin, const std::array<double, 3> &boxMax ) const {
193
194 double distanceTolerance = getDistanceTolerance();
195
196 std::array<double,3> cellBoxMin;
197 std::array<double,3> cellBoxMax;
198 m_mesh->evalCellBoundingBox(id, &cellBoxMin, &cellBoxMax);
199
200 return CGElem::intersectBoxBox(cellBoxMin, cellBoxMax, boxMin, boxMax, 3, distanceTolerance);
201}
202
203# if BITPIT_ENABLE_MPI
204
208void LevelSetKernel::initializeCommunicator()
209{
210 // The communicator has to be valid
211 MPI_Comm communicator = m_mesh->getCommunicator();
212 if (communicator == MPI_COMM_NULL) {
213 throw std::runtime_error ("Levelset communicator is not valid");
214 }
215
216 // Communication can be set just once
217 if (isCommunicatorSet()) {
218 int comparison;
219 MPI_Comm_compare(communicator, m_communicator, &comparison);
220 if (comparison == MPI_IDENT || comparison == MPI_CONGRUENT) {
221 return;
222 } else {
223 throw std::runtime_error ("Levelset communicator cannot be modified.");
224 }
225 }
226
227 // Create a duplicate of the patch communicator
228 MPI_Comm_dup(communicator, &m_communicator);
229}
230
234void LevelSetKernel::freeCommunicator() {
235
236 if (!isCommunicatorSet()) {
237 return;
238 }
239
240 int finalizedCalled;
241 MPI_Finalized(&finalizedCalled);
242 if (finalizedCalled) {
243 return;
244 }
245
246 MPI_Comm_free(&m_communicator);
247}
248
254
255 return m_communicator;
256}
257
265
266 return (getCommunicator() != MPI_COMM_NULL);
267}
268
274std::unique_ptr<DataCommunicator> LevelSetKernel::createDataCommunicator( ) const {
275
276 std::unique_ptr<DataCommunicator> dataCommunicator;
277 if (isCommunicatorSet()) {
278 dataCommunicator = std::unique_ptr<DataCommunicator>(new DataCommunicator(getCommunicator())) ;
279 }
280
281 return dataCommunicator;
282}
283
284#endif
285
298 : LevelSetKernel(patch, fillIn),
299 m_cellCacheCollection(std::unique_ptr<CellCacheCollection>(new CellCacheCollection(&(patch->getCells()))))
300{
301}
302
310{
311 for (CellCacheCollection::Item &cacheItem : *m_cellCacheCollection) {
312 if (!cacheItem.hasCache()) {
313 continue;
314 }
315
316 if (release) {
317 cacheItem.destroyCache();
318 } else {
319 cacheItem.getCache()->clear();
320 }
321 }
322}
323
335
347
354bool LevelSetCachedKernel::update( const std::vector<adaption::Info> &adaptionData ) {
355
356 // Update base class
357 bool updated = LevelSetKernel::update( adaptionData );
358 if (!updated) {
359 return false;
360 }
361
362 // Update cell cache collection
363 for (const adaption::Info &adaptionInfo : adaptionData) {
364 if (adaptionInfo.entity != adaption::Entity::ENTITY_CELL) {
365 continue;
366 }
367
368 for (CellCacheCollection::Item &cacheItem : *m_cellCacheCollection) {
369 if (!cacheItem.hasCache()) {
370 continue;
371 }
372
373 CellCacheCollection::Cache *cache = cacheItem.getCache();
374 cache->erase(adaptionInfo.previous);
375 }
376 }
377
378 for (CellCacheCollection::Item &cacheItem : *m_cellCacheCollection) {
379 if (!cacheItem.hasCache()) {
380 continue;
381 }
382
383 CellCacheCollection::Cache *cache = cacheItem.getCache();
385 cache->reserve(getMesh()->getCells().size());
386 } else {
387 cache->shrink_to_fit();
388 }
389 }
390
391 // The kernel has been updated
392 return true;
393
394}
395
396}
The DataCommunicator class provides the infrastructure needed to exchange data among processes.
The class ElementCacheCollection allows to store a collection of caches for the elements of a mesh.
The class LevelSetCache is the base class for defining caches.
std::size_t erase(const Keys &keys)
LevelSetCachedKernel(VolumeKernel *, LevelSetFillIn fillIn)
bool update(const std::vector< adaption::Info > &) override
CellCacheCollection & getCellCacheCollection()
void clearCaches(bool release=false)
std::unique_ptr< CellCacheCollection > m_cellCacheCollection
Mesh specific implementation to calculate the levelset function.
virtual VolumeKernel * getMesh() const
LevelSetFillIn getExpectedFillIn() const
virtual bool update(const std::vector< adaption::Info > &)
double getDistanceTolerance() const
double isCellInsideBoundingBox(long, const std::array< double BITPIT_COMMA 3 > &, const std::array< double, 3 > &) const
virtual bool intersectCellPlane(long, const std::array< double, 3 > &, const std::array< double, 3 > &, double)
MPI_Comm getCommunicator() const
bool isPointInCell(long, const std::array< double, 3 > &) const
std::unique_ptr< DataCommunicator > createDataCommunicator() const
LevelSetFillIn m_expectedFillIn
PiercedVector< Cell > & getCells()
virtual void evalCellBoundingBox(long id, std::array< double, 3 > *minPoint, std::array< double, 3 > *maxPoint) const
const MPI_Comm & getCommunicator() const
double getTol() const
The VolumeKernel class provides an interface for defining volume patches.
bool isPointInside(double x, double y, double z) const
bool intersectPlaneBox(array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:1952
bool intersectBoxBox(array3D const &, array3D const &, array3D const &, array3D const &, int dim=3, const double distanceTolerance=DEFAULT_DISTANCE_TOLERANCE)
Definition CG_elem.cpp:2125
The Info struct defines the information associated to an adaption.
Definition adaption.hpp:63
--- layout: doxygen_footer ---