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
79
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
581
586std::vector<LevelSetObject *> LevelSet::getObjectPtrs( ) const{
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) {
683 object->setCellBulkEvaluationMode(LevelSetBulkEvaluationMode::SIGN_PROPAGATION);
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)
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.
virtual bool isPrimary() const
void setNarrowBandSize(double size)
virtual void setKernel(LevelSetKernel *)
std::size_t getReferenceCount() const
void update(const std::vector< adaption::Info > &adaptionData)
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.
Logger & warning(log::Visibility defaultVisibility)
Definition logger.cpp:1821