Loading...
Searching...
No Matches
levelSet.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 "bitpit_operators.hpp"
26# include "bitpit_patchkernel.hpp"
27# include "bitpit_surfunstructured.hpp"
28# include "bitpit_volcartesian.hpp"
29# include "bitpit_voloctree.hpp"
30# include "bitpit_volunstructured.hpp"
31
32# include "levelSetCommon.hpp"
33# include "levelSetKernel.hpp"
34# include "levelSetCartesianKernel.hpp"
35# include "levelSetComplementObject.hpp"
36# include "levelSetOctreeKernel.hpp"
37# include "levelSetObject.hpp"
38# include "levelSetProxyObject.hpp"
39# include "levelSetBooleanObject.hpp"
40# include "levelSetSegmentationObject.hpp"
41# include "levelSetMaskObject.hpp"
42# include "levelSetUnstructuredKernel.hpp"
43
44# include "levelSet.hpp"
45
46namespace bitpit {
47
84
85 m_expectedFillIn = expectedFillIn ;
86
87 m_objects.clear() ;
88
89 m_signedDistance = true ;
90
91 m_forceSignPropagation = false;
92 m_signPropagationEnabled = false;
93
94 m_narrowBandSize = 0;
95
96}
97
103 m_kernel.reset();
104}
105
113void LevelSet::update( const std::vector<adaption::Info> &adaptionData ){
114
115 assert(m_kernel && "LevelSet::setMesh() must be called prior to LevelSet::update()");
116
117 // Update kernel
118 bool updated = m_kernel->update( adaptionData ) ;
119 if (!updated) {
120 return;
121 }
122
123 // Update objects
124 for( int id : m_orderedObjectsIds){
125 LevelSetObject *object = m_objects.at(id).get() ;
126 object->update( adaptionData ) ;
127 }
128}
129
146 return m_narrowBandSize;
147}
148
165 // Set narrow band size
166 m_narrowBandSize = std::max(size, 0.);
167
168 // Set object narrow band size
169 for (auto &objectEntry : m_objects) {
170 LevelSetObject *object = objectEntry.second.get();
171 object->setNarrowBandSize(size);
172 }
173}
174
184
185 // Mesh can be set only once
186 if (m_kernel) {
187 throw std::runtime_error ("Mesh can be set just once.");
188 }
189
190 // Create the kernel
191 if (VolCartesian *cartesian = dynamic_cast<VolCartesian *>(mesh)) {
192 m_kernel = std::unique_ptr<LevelSetKernel>(new LevelSetCartesianKernel(*cartesian, m_expectedFillIn));
193 } else if (VolOctree *octree = dynamic_cast<VolOctree *>(mesh)) {
194 m_kernel = std::unique_ptr<LevelSetKernel>(new LevelSetOctreeKernel(*octree, m_expectedFillIn));
195 } else if (VolUnstructured *unstructured = dynamic_cast<VolUnstructured*>(mesh)) {
196 m_kernel = std::unique_ptr<LevelSetKernel>(new LevelSetUnstructuredKernel(*unstructured, m_expectedFillIn));
197 } else {
198 throw std::runtime_error ("Unable to create the levelset kernel. Mesh type non supported.");
199 }
200
201 // Assign the kernel to the existing objects
202 for( int id : m_orderedObjectsIds){
203 LevelSetObject *object = m_objects.at(id).get() ;
204 object->setKernel(m_kernel.get());
205 }
206
207}
208
217int LevelSet::addObject( std::unique_ptr<SurfUnstructured> &&segmentation, double angle, int id ) {
218
219 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, std::move(segmentation), angle));
220
221 return registerObject(std::move(object));
222}
223
232int LevelSet::addObject( SurfUnstructured *segmentation, double angle, int id ) {
233
234 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, segmentation, angle));
235
236 return registerObject(std::move(object));
237}
238
248int LevelSet::addObject( SurfUnstructured *segmentation, double angle, LevelSetSurfaceSmoothing surfaceSmoothing, int id ) {
249
250 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, segmentation, angle, surfaceSmoothing));
251
252 return registerObject(std::move(object));
253}
254
263int LevelSet::addObject( std::unique_ptr<SurfaceKernel> &&segmentation, double angle, int id ) {
264
265 auto surfUnstructured = std::unique_ptr<SurfUnstructured>(dynamic_cast<SurfUnstructured *>(segmentation.release())) ;
266 if (!surfUnstructured) {
267 throw std::runtime_error ("Segmentation type not supported");
268 }
269
270 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, std::move(surfUnstructured), angle));
271
272 return registerObject(std::move(object));
273}
274
283int LevelSet::addObject( SurfaceKernel *segmentation, double angle, int id ) {
284
285 SurfUnstructured *surfUnstructured = dynamic_cast<SurfUnstructured *>(segmentation);
286 if (!surfUnstructured) {
287 throw std::runtime_error ("Segmentation type not supported");
288 }
289
290 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, surfUnstructured, angle));
291
292 return registerObject(std::move(object));
293}
294
304int LevelSet::addObject( SurfaceKernel *segmentation, double angle, LevelSetSurfaceSmoothing surfaceSmoothing, int id ) {
305
306 SurfUnstructured *surfUnstructured = dynamic_cast<SurfUnstructured *>(segmentation);
307 if (!surfUnstructured) {
308 throw std::runtime_error ("Segmentation type not supported");
309 }
310
311 auto object = std::unique_ptr<LevelSetObject>(new LevelSetSegmentationObject(id, surfUnstructured, angle, surfaceSmoothing));
312
313 return registerObject(std::move(object));
314}
315
323int LevelSet::addObject( const std::unordered_set<long> &list, int id ) {
324
325 assert(m_kernel && " levelset: setMesh must be called before adding a mask object ");
326
327 auto object = std::unique_ptr<LevelSetObject>(new LevelSetMaskObject(id, list, *m_kernel->getMesh()));
328
329 return registerObject(std::move(object));
330}
331
341int LevelSet::addObject( const std::vector<long> &list, long refInterface, bool invert, int id ) {
342
343 assert(m_kernel && " levelset: setMesh must be called before adding a mask object ");
344
345 auto object = std::unique_ptr<LevelSetObject>(new LevelSetMaskObject(id, list, refInterface, invert, *m_kernel->getMesh()));
346
347 return registerObject(std::move(object));
348};
349
356int LevelSet::addObject( std::unique_ptr<LevelSetObject> &&object ) {
357
358 return registerObject(std::move(object));
359};
360
366int LevelSet::registerObject( std::unique_ptr<LevelSetObject> &&object ) {
367
368 // Set object id
369 int id = object->getId();
370 if (id == levelSetDefaults::OBJECT) {
371 id = m_objectIdentifierGenerator.generate();
372 object->setId(id);
373 } else {
374 m_objectIdentifierGenerator.setAssigned(id);
375 }
376
377 // Set object properties
378 object->setDefaultLevelSetSigndness(m_signedDistance);
379 object->setNarrowBandSize(m_narrowBandSize);
380 if (m_forceSignPropagation) {
381 if (m_signPropagationEnabled) {
382 object->setCellBulkEvaluationMode(LevelSetBulkEvaluationMode::SIGN_PROPAGATION);
383 } else {
384 object->setCellBulkEvaluationMode(LevelSetBulkEvaluationMode::NONE);
385 }
386 }
387
388 // Set object kernel
389 if (m_kernel) {
390 object->setKernel(m_kernel.get());
391 }
392
393 // Add the object to the levelset
394 m_objects[id] = std::move(object) ;
395 registerObjectId(id);
396 incrementObjectsReferenceCount(id);
397
398 return id;
399}
400
405 m_orderedObjectsIds.clear();
406 m_objectIdentifierGenerator.reset();
407 m_objects.clear();
408}
409
417 return unregisterObject(id, false);
418
419}
420
430bool LevelSet::unregisterObject(int id, bool force) {
431 if( !force && !isObjectRemovable(id) ) {
432 return false;
433 }
434
435 decrementObjectsReferenceCount(id);
436 unregisterObjectId(id);
437 m_objectIdentifierGenerator.trash(id);
438 m_objects.erase(id);
439
440 return true;
441
442}
443
452 auto objectItr = m_objects.find(id) ;
453 if( objectItr == m_objects.end() ){
454 return false;
455 }
456
457 const LevelSetObject *object = objectItr->second.get() ;
458 if( object->getReferenceCount() > 0 ) {
459 return false;
460 }
461
462 return true;
463
464}
465
478void LevelSet::registerObjectId( int id ) {
479
480 // Add the id from the list
481 //
482 // Ids should be sorted according to the order in which they corresponding objects should be
483 // processed: first the ids of the primary objects (in the order the objects were added to
484 // the levelset) and then the ids of the other objects (in the order the objects were added
485 // to the levelset).
486 std::vector<int>::iterator idItr;
487 if(getObjectPtr(id)->isPrimary()){
488 std::vector<int>::iterator orderedIdsBegin = m_orderedObjectsIds.begin();
489 std::vector<int>::iterator orderedIdsEnd = m_orderedObjectsIds.end();
490
491 for (idItr = orderedIdsBegin; idItr != orderedIdsEnd; ++idItr) {
492 int candidateId = *idItr ;
493 const LevelSetObject *candidateObject = getObjectPtr(candidateId) ;
494 if( !candidateObject->isPrimary() ){
495 break;
496 }
497 }
498 } else {
499 idItr = m_orderedObjectsIds.end();
500 }
501
502 m_orderedObjectsIds.insert(idItr, id) ;
503
504}
505
513void LevelSet::unregisterObjectId(int id){
514
515 // Remove the id from the list
516 std::vector<int>::iterator orderedIdsBegin = m_orderedObjectsIds.begin();
517 std::vector<int>::iterator orderedIdsEnd = m_orderedObjectsIds.end();
518
519 std::vector<int>::iterator idItr = std::find(orderedIdsBegin, orderedIdsEnd, id);
520 assert(idItr != orderedIdsEnd);
521 m_orderedObjectsIds.erase(idItr);
522
523}
524
529void LevelSet::incrementObjectsReferenceCount(int parentId) {
530
531 const LevelSetObject *parentObject = getObjectPtr(parentId);
532 if( parentObject->isPrimary() ){
533 return;
534 }
535
536 if( const LevelSetProxyBaseObject *parentProxyObject = dynamic_cast<const LevelSetProxyBaseObject *>(parentObject) ){
537 for ( int sourceObjectId : parentProxyObject->getSourceObjectIds() ){
538 getObjectPtr(sourceObjectId)->incrementReferenceCount();
539 }
540 }
541
542}
543
548void LevelSet::decrementObjectsReferenceCount(int parentId) {
549
550 const LevelSetObject *parentObject = getObjectPtr(parentId);
551 if( parentObject->isPrimary() ){
552 return;
553 }
554
555 if( const LevelSetProxyBaseObject *parentProxyObject = dynamic_cast<const LevelSetProxyBaseObject *>(parentObject) ){
556 for ( int sourceObjectId : parentProxyObject->getSourceObjectIds() ){
557 getObjectPtr(sourceObjectId)->decrementReferenceCount();
558 }
559 }
560
561}
562
570 return getObject<LevelSetObject>(id);
571}
572
579 return getObjectPtr<LevelSetObject>(id);
580}
581
586std::vector<LevelSetObject *> LevelSet::getObjectPtrs( ) const{
587 return getObjectPtrs<LevelSetObject>();
588}
589
595 return m_objects.size() ;
596}
597
602std::vector<int> LevelSet::getObjectIds( ) const{
603 std::vector<int> ids ;
604 ids.reserve(m_objects.size()) ;
605 for(const auto &entry : m_objects) {
606 ids.push_back(entry.first) ;
607 }
608
609 return ids ;
610}
611
616void LevelSet::dump( std::ostream &stream ) const{
617
618 utils::binary::write(stream, m_expectedFillIn);
619 utils::binary::write(stream, m_signedDistance);
620 utils::binary::write(stream, m_forceSignPropagation);
621 utils::binary::write(stream, m_signPropagationEnabled);
622 utils::binary::write(stream, m_narrowBandSize);
623
624 m_objectIdentifierGenerator.dump(stream);
625 for( const auto &object : m_objects ){
626 object.second->dump( stream ) ;
627 }
628 utils::binary::write(stream, m_orderedObjectsIds);
629
630}
631
636void LevelSet::restore( std::istream &stream ){
637
638 utils::binary::read(stream, m_expectedFillIn);
639 utils::binary::read(stream, m_signedDistance);
640 utils::binary::read(stream, m_forceSignPropagation);
641 utils::binary::read(stream, m_signPropagationEnabled);
642 utils::binary::read(stream, m_narrowBandSize);
643
644 m_objectIdentifierGenerator.restore(stream);
645 for( const auto &object : m_objects ){
646 object.second->restore( stream ) ;
647 }
648 utils::binary::read(stream, m_orderedObjectsIds);
649
650}
651
656void LevelSet::setSign(bool flag){
657 m_signedDistance = flag;
658
659}
660
674 // Set propagation
675 m_forceSignPropagation = true;
676 m_signPropagationEnabled = flag;
677
678 // Set object bulk evaluation mode
679 for (auto &objectEntry : m_objects) {
680 LevelSetObject *object = objectEntry.second.get();
681 if (m_forceSignPropagation) {
682 if (m_signPropagationEnabled) {
684 } else {
685 object->setCellBulkEvaluationMode(LevelSetBulkEvaluationMode::NONE);
686 }
687 }
688 }
689}
690
706double LevelSet::getSizeNarrowBand() const{
707 return getNarrowBandSize();
708}
709
725void LevelSet::setSizeNarrowBand(double size){
726 return setNarrowBandSize(size);
727}
728
734void LevelSet::compute(){
735
736 // Nothing to do
737
738}
739
747void LevelSet::compute( int id ){
748
749 BITPIT_UNUSED(id);
750
751 // Nothing to do
752
753}
754
762void LevelSet::compute( const std::vector<int> &ids ){
763
764 BITPIT_UNUSED(ids);
765
766 // Nothing to do
767
768}
769
780void LevelSet::update( const std::vector<adaption::Info> &adaptionData, int id){
781
782 BITPIT_UNUSED(id);
783
784 log::warning() << " It is not possible to update the levelset for a specific objects." << std::endl;
785 log::warning() << " Levelset will be computed for all the objects." << std::endl;
786
787 update(adaptionData);
788
789}
790
801void LevelSet::update( const std::vector<adaption::Info> &adaptionData, const std::vector<int> &ids ){
802
803 BITPIT_UNUSED(ids);
804
805 log::warning() << " It is not possible to update the levelset for a specific objects." << std::endl;
806 log::warning() << " Levelset will be computed for all the objects." << std::endl;
807
808 update(adaptionData);
809
810}
811
812#if BITPIT_ENABLE_MPI
817void LevelSet::partition( const std::vector<adaption::Info> &adaptionData ){
818
819 update ( adaptionData ) ;
820
821}
822#endif
823
824}
825
void setAssigned(id_type id)
void restore(std::istream &stream)
void dump(std::ostream &stream) const
Implements LevelSetKernel for cartesian meshes.
Implements the levelset around a set of cells or interfaces of the kernel.
Interface class for all objects with respect to whom the levelset function may be computed.
void setCellBulkEvaluationMode(LevelSetBulkEvaluationMode evaluationMode)
virtual bool isPrimary() const
void setNarrowBandSize(double size)
std::size_t getReferenceCount() const
Implements LevelSetKernel for octree meshes.
Implements visitor pattern fo segmentated geometries.
Implements LevelSetKernel for unstructured meshes.
LevelSetObject & getObject(int) const
Definition levelSet.cpp:569
void setNarrowBandSize(double size=0)
Definition levelSet.cpp:164
void setPropagateSign(bool)
Definition levelSet.cpp:673
int getObjectCount() const
Definition levelSet.cpp:594
void restore(std::istream &)
Definition levelSet.cpp:636
void setSign(bool)
Definition levelSet.cpp:656
LevelSetObject * getObjectPtr(int) const
Definition levelSet.cpp:578
void setMesh(VolumeKernel *mesh)
Definition levelSet.cpp:183
std::vector< LevelSetObject * > getObjectPtrs() const
Definition levelSet.cpp:586
std::vector< int > getObjectIds() const
Definition levelSet.cpp:602
void update(const std::vector< adaption::Info > &adaptionData)
Definition levelSet.cpp:113
void dump(std::ostream &) const
Definition levelSet.cpp:616
double getNarrowBandSize() const
Definition levelSet.cpp:145
LevelSet(LevelSetFillIn expectedFillIn=LevelSetFillIn::SPARSE)
Definition levelSet.cpp:83
bool removeObject(int)
Definition levelSet.cpp:416
void partition(const std::vector< adaption::Info > &)
Definition levelSet.cpp:817
int addObject(LevelSetBooleanOperation, int, int, int id=levelSetDefaults::OBJECT)
Definition levelSet.tpp:60
bool isObjectRemovable(int)
Definition levelSet.cpp:451
The SurfUnstructured class defines an unstructured surface triangulation.
The SurfaceKernel class provides an interface for defining surface patches.
The VolCartesian defines a Cartesian patch.
The VolOctree defines a Octree patch.
Definition voloctree.hpp:37
The VolUnstructured class defines a dummy unstructured volume patch.
The VolumeKernel class provides an interface for defining volume patches.
void write(std::ostream &stream, const std::vector< bool > &container)
void read(std::istream &stream, std::vector< bool > &container)
#define BITPIT_UNUSED(variable)
Definition compiler.hpp:63
@ SIGN_PROPAGATION
Sign is propagated from the narrow band, no other data will be evaluated.
@ NONE
No data is evaluated.
Logger & warning(log::Visibility defaultVisibility)
Definition logger.cpp:1812
--- layout: doxygen_footer ---