24 gsAdaptiveMeshing<T>::gsAdaptiveMeshing()
30 gsAdaptiveMeshing<T>::gsAdaptiveMeshing(gsFunctionSet<T> & input)
39 void gsAdaptiveMeshing<T>::rebuild()
45 this->_makeMap(m_input,m_indices,m_boxes);
48 for (
typename indexMapType::iterator it=m_indices.begin(); it!=m_indices.end(); it++)
49 check &= gsHBoxEqual<2,T>()(it->first,*m_boxes[it->second]);
51 for (
typename boxMapType::iterator it=m_boxes.begin(); it!=m_boxes.end(); it++)
52 check &= it->first==m_indices[*it->second];
54 GISMO_ASSERT(check,
"Something went wrong in the construction of the mappers");
58 void gsAdaptiveMeshing<T>::_makeMap(
const gsFunctionSet<T> * input,
typename gsAdaptiveMeshing<T>::indexMapType & indexMap,
typename gsAdaptiveMeshing<T>::boxMapType & boxMap)
63 const gsBasis<T> * basis =
nullptr;
75 const gsMultiPatch<T> * mp;
76 const gsMultiBasis<T> * mb;
77 for (
index_t patchInd=0; patchInd < input->nPieces(); ++patchInd)
80 if (
nullptr != (mp =
dynamic_cast<const gsMultiPatch<T>*
>(input)) ) basis = &(mp->basis(patchInd));
81 if (
nullptr != (mb =
dynamic_cast<const gsMultiBasis<T>*
>(input)) ) basis = &(mb->basis(patchInd));
82 GISMO_ENSURE(basis!=
nullptr,
"Object is not gsMultiBasis or gsMultiPatch");
84 typename gsBasis<T>::domainIter domIt = basis->makeDomainIterator();
85 gsHDomainIterator<T,2> * domHIt =
nullptr;
86 domHIt =
dynamic_cast<gsHDomainIterator<T,2> *
>(domIt.get());
94 for (; domHIt->good(); domHIt->next())
99 HBox box(domHIt,patchInd);
100 std::pair<typename gsAdaptiveMeshing<T>::indexMapType::iterator,
bool> mapIt = indexMap.insert({box,c});
104 boxMap.insert({c,
const_cast<gsHBox<2,real_t> *
>(&(mapIt.first->first))});
123 void gsAdaptiveMeshing<T>::_assignErrors(boxMapType & container,
const std::vector<T> & elError)
125 GISMO_ASSERT(elError.size()==container.size(),
"The number of errors must be the same as the number of elements, but "<<elError.size()<<
"!="<<container.size());
128 if (m_refRule == PBULK || m_crsRule == PBULK)
129 for (
typename boxMapType::iterator it = container.begin(); it!=container.end(); it++, k++)
130 it->second->setAndProjectError(elError[k],m_alpha,m_beta);
132 for (
typename boxMapType::iterator it = container.begin(); it!=container.end(); it++, k++)
133 it->second->setError(elError[k]);
135 m_totalError = _totalError(m_boxes);
136 m_maxError = _maxError(m_boxes);
137 if (m_alpha!=-1 && m_beta!=-1)
139 const gsBasis<T> * basis =
nullptr;
141 const gsMultiPatch<T> * mp;
142 const gsMultiBasis<T> * mb;
143 if (
nullptr != (mp =
dynamic_cast<const gsMultiPatch<T>*
>(m_input)) ) basis = &(mp->basis(patchInd));
144 if (
nullptr != (mb =
dynamic_cast<const gsMultiBasis<T>*
>(m_input)) ) basis = &(mb->basis(patchInd));
145 GISMO_ASSERT(basis!=
nullptr,
"Object is not gsMultiBasis or gsMultiPatch");
147 m_uniformRefError = math::pow(1/2.,m_alpha * basis->minDegree() + m_beta) * m_totalError;
148 m_uniformCrsError = math::pow( 2.,m_alpha * basis->minDegree() + m_beta) * m_totalError;
152 m_uniformRefError = 0;
153 m_uniformCrsError = 0;
200 template<
bool _coarsen,
bool _admissible>
205 switch (refCriterion)
208 _markThreshold<_coarsen,_admissible>(m_boxes,predicates,elMarked);
211 _markPercentage<_coarsen,_admissible>(m_boxes,predicates,elMarked);
214 _markFraction<_coarsen,_admissible>(m_boxes,predicates,elMarked);
217 _markProjectedFraction<_coarsen,_admissible>(m_boxes,predicates,elMarked);
233 void gsAdaptiveMeshing<T>::_crsPredicates_into(
const HBoxContainer & markedRef, std::vector<gsHBoxCheck<2,T> *> & predicates)
235 predicates.push_back(
new gsMinLvlCompare<2,T>(0));
236 predicates.push_back(
new gsOverlapCompare<2,T>(markedRef,m_m));
240 void gsAdaptiveMeshing<T>::_refPredicates_into(std::vector<gsHBoxCheck<2,T> *> & predicates)
242 predicates.push_back(
new gsMaxLvlCompare<2,T>(m_maxLvl));
247 std::vector<index_t> gsAdaptiveMeshing<T>::_sortPermutation(
const boxMapType & container)
249 std::vector<index_t> idx(container.size());
250 std::iota(idx.begin(),idx.end(),0);
251 std::stable_sort(idx.begin(), idx.end(),
252 [&container](
size_t i1,
size_t i2) {
253 return container.at(i1)->error() < container.at(i2)->error();});
259 std::vector<index_t> gsAdaptiveMeshing<T>::_sortPermutationProjectedRef(
const boxMapType & container)
261 std::vector<index_t> idx(container.size());
262 std::iota(idx.begin(),idx.end(),0);
263 std::stable_sort(idx.begin(), idx.end(),
264 [&container](
size_t i1,
size_t i2) {
265 return container.at(i1)->projectedImprovement() < container.at(i2)->projectedImprovement();});
271 std::vector<index_t> gsAdaptiveMeshing<T>::_sortPermutationProjectedCrs(
const boxMapType & container)
273 std::vector<index_t> idx(container.size());
274 std::iota(idx.begin(),idx.end(),0);
275 std::stable_sort(idx.begin(), idx.end(),
276 [&container](
size_t i1,
size_t i2) {
277 return container.at(i1)->projectedSetBack() < container.at(i2)->projectedSetBack();});
294 typename gsAdaptiveMeshing<T>::HBox * gsAdaptiveMeshing<T>::_boxPtr(
const HBox & box)
const
297 HBox * boxPtr = m_boxes.at(m_indices.at(box));
303 bool gsAdaptiveMeshing<T>::_checkBox(
const HBox & box,
const std::vector<gsHBoxCheck<2,T> *> predicates)
const
306 for (
typename std::vector<gsHBoxCheck<2,T>*>::const_iterator errIt = predicates.begin(); errIt!=predicates.end(); errIt++)
307 check &= (*errIt)->check(box);
312 bool gsAdaptiveMeshing<T>::_checkBoxes(
const typename HBox::Container & boxes,
const std::vector<gsHBoxCheck<2,T> *> predicates)
const
315 for (
typename HBox::cIterator it = boxes.begin(); it!=boxes.end(); it++)
316 check &= _checkBox(*it,predicates);
325 void gsAdaptiveMeshing<T>::_addAndMark( HBox & box,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
327 _boxPtr(box)->mark();
328 elMarked.add(*_boxPtr(box));
332 void gsAdaptiveMeshing<T>::_addAndMark(
typename HBox::Container & boxes,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
334 for (
typename HBox::Iterator it = boxes.begin(); it!=boxes.end(); it++)
335 _addAndMark(*it,elMarked);
339 void gsAdaptiveMeshing<T>::_setContainerProperties(
typename HBox::Container & boxes )
const
341 for (
typename HBox::Iterator it = boxes.begin(); it!=boxes.end(); it++)
346 it->setAndProjectError(_boxPtr(*it)->error(),m_alpha,m_beta);
351 T gsAdaptiveMeshing<T>::_totalError(
const boxMapType & elements)
355 auto accumulate_error_ptr = [](
const T & val,
const typename boxMapType::value_type & b)
356 {
return val + b.second->error(); };
357 T totalError = std::accumulate(elements.begin(),elements.end(),(T)( 0 ),accumulate_error_ptr);
366 template<
bool _coarsen,
bool _admissible>
367 typename std::enable_if< _coarsen && _admissible, void>::type
368 gsAdaptiveMeshing<T>::_markFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
370 gsDebug<<
"Fraction marking for coarsening...\n";
371 T cummulErrMarked = T(0);
372 T errorMarkSum = m_crsParam * m_totalError;
375 auto accumulate_error = [](
const T & val,
const typename boxContainer::value_type & b)
376 {
return val + b.error(); };
378 auto loop_action = [
this,&elements,&predicates,&cummulErrMarked,&errorMarkSum,&elMarked,&accumulate_error]
382 HBox_ptr box = elements.at(index);
384 if (_boxPtr(*box)->marked() || !_checkBox(*box,predicates))
388 typename HBox::Container sibs = box->getSiblings();
389 _setContainerProperties(sibs);
390 if (!gsHBoxUtils<2,T>::allActive(sibs))
393 HBoxContainer siblings(sibs);
394 T siblingError = std::accumulate(sibs.begin(),sibs.end(),(T)( 0 ),accumulate_error);
397 if (_checkBoxes(sibs,predicates))
399 cummulErrMarked += siblingError;
400 _addAndMark(sibs,elMarked);
401 cummulErrMarked += box->error();
402 _addAndMark(*box,elMarked);
405 return (cummulErrMarked > errorMarkSum);
408 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
409 elMarked = HBoxUtils::Unique(elMarked);
410 gsDebug<<
"[Mark fraction] Marked "<<elMarked.totalSize()<<
" elements with marked error = "<<cummulErrMarked<<
" and threshold = "<<errorMarkSum<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
415 template<
bool _coarsen,
bool _admissible>
416 typename std::enable_if< _coarsen && !_admissible, void>::type
417 gsAdaptiveMeshing<T>::_markFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
419 gsDebug<<
"Fraction marking for coarsening...\n";
420 T cummulErrMarked = T(0);
421 T errorMarkSum = m_crsParam * m_totalError;
423 auto loop_action = [
this,&elements,&predicates,&cummulErrMarked,&errorMarkSum,&elMarked]
427 HBox_ptr box = elements.at(index);
430 if (_checkBox(*box,predicates))
432 cummulErrMarked += box->error();
433 _addAndMark(*box,elMarked);
436 return (cummulErrMarked > errorMarkSum);
439 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
440 elMarked = HBoxUtils::Unique(elMarked);
441 gsDebug<<
"[Mark fraction] Marked "<<elMarked.totalSize()<<
" elements with marked error = "<<cummulErrMarked<<
" and threshold = "<<errorMarkSum<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
445 template<
bool _coarsen,
bool _admissible>
446 typename std::enable_if<!_coarsen && _admissible, void>::type
447 gsAdaptiveMeshing<T>::_markFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
449 gsDebug<<
"Fraction marking (admissible) for refinement...\n";
450 T cummulErrMarked = T(0);
451 T errorMarkSum = m_refParam * m_totalError;
454 auto accumulate_error = [](
const T & val,
const typename boxContainer::value_type & b)
455 {
return val + b.error(); };
457 auto loop_action = [
this,&elements,&predicates,&cummulErrMarked,&errorMarkSum,&elMarked,&accumulate_error]
461 HBox_ptr box = elements.at(index);
462 if (_boxPtr(*box)->marked())
468 typename HBox::Container neighborhood = HBoxUtils::toContainer(HBoxUtils::markAdmissible(*box,m_m));
469 _setContainerProperties(neighborhood);
470 T neighborhoodError = std::accumulate(neighborhood.begin(),neighborhood.end(),(T)( 0 ),accumulate_error);
479 if (_checkBoxes(neighborhood,predicates))
481 cummulErrMarked += neighborhoodError;
482 _addAndMark(neighborhood,elMarked);
485 return (cummulErrMarked > errorMarkSum);
488 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
489 elMarked = HBoxUtils::Unique(elMarked);
490 gsDebug<<
"[Mark fraction] Marked "<<elMarked.totalSize()<<
" elements with marked error = "<<cummulErrMarked<<
" and threshold = "<<errorMarkSum<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
494 template<
bool _coarsen,
bool _admissible>
495 typename std::enable_if<!_coarsen && !_admissible, void>::type
496 gsAdaptiveMeshing<T>::_markFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
498 gsDebug<<
"Fraction marking (not admissible) for refinement...\n";
499 T cummulErrMarked = T(0);
500 T errorMarkSum = m_refParam * m_totalError;
502 auto loop_action = [
this,&elements,&predicates,&cummulErrMarked,&errorMarkSum,&elMarked]
505 HBox_ptr box = elements.at(index);
511 if (_checkBox(*box,predicates))
513 cummulErrMarked += box->error();
514 _addAndMark(*box,elMarked);
516 return (cummulErrMarked > errorMarkSum);
520 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
521 elMarked = HBoxUtils::Unique(elMarked);
522 gsDebug<<
"[Mark fraction] Marked "<<elMarked.totalSize()<<
" elements with marked error = "<<cummulErrMarked<<
" and threshold = "<<errorMarkSum<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
526 template<
bool _coarsen,
bool _admissible>
527 typename std::enable_if< _coarsen && _admissible, void>::type
528 gsAdaptiveMeshing<T>::_markProjectedFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
530 gsDebug<<
"Projected fraction (admissible) marking for coarsening...\n";
531 T targetError = m_crsParamExtra;
532 if (m_totalError > targetError)
534 if (m_uniformCrsError < targetError)
536 this->_markFraction_impl<_coarsen,_admissible>(elements,predicates,elMarked);
539 T projectedError = m_totalError;
542 auto accumulate_improvement = [](
const T & val,
const typename boxContainer::value_type & b)
543 {
return val + b.projectedErrorCrs() - b.error(); };
545 auto loop_action = [
this,&elements,&predicates,&projectedError,&targetError,&elMarked,&accumulate_improvement]
549 HBox_ptr box = elements.at(index);
551 if (_boxPtr(*box)->marked() || !_checkBox(*box,predicates))
555 typename HBox::Container sibs = box->getSiblings();
556 _setContainerProperties(sibs);
557 if (!gsHBoxUtils<2,T>::allActive(sibs))
560 HBoxContainer siblings(sibs);
561 T siblingSetBack = std::accumulate(sibs.begin(),sibs.end(),(T)( 0 ),accumulate_improvement);
564 if (_checkBoxes(sibs,predicates))
566 projectedError += siblingSetBack;
567 _addAndMark(sibs,elMarked);
568 projectedError += box->projectedErrorCrs() - box->error();
569 _addAndMark(*box,elMarked);
573 return (projectedError > targetError);
576 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
577 elMarked = HBoxUtils::Unique(elMarked);
578 gsDebug<<
"[Mark projected fraction] Marked "<<elMarked.totalSize()<<
" elements with projected error = "<<projectedError<<
" and target error = "<<targetError<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
583 template<
bool _coarsen,
bool _admissible>
584 typename std::enable_if< _coarsen && !_admissible, void>::type
586 gsAdaptiveMeshing<T>::_markProjectedFraction_impl(
const boxMapType &,
const std::vector<gsHBoxCheck<2,T> *>,
typename gsAdaptiveMeshing<T>::HBoxContainer &)
const
617 template<
bool _coarsen,
bool _admissible>
618 typename std::enable_if<!_coarsen && _admissible, void>::type
619 gsAdaptiveMeshing<T>::_markProjectedFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
621 gsDebug<<
"Projected fraction (admissible) marking for refinement...\n";
622 T targetError = m_refParamExtra;
623 if (m_totalError < targetError)
625 if (m_uniformRefError > targetError)
627 this->_markFraction_impl<_coarsen,_admissible>(elements,predicates,elMarked);
630 T projectedError = m_totalError;
633 auto accumulate_improvement = [](
const T & val,
const typename boxContainer::value_type & b)
635 return val + b.error() - b.projectedErrorRef();
638 auto loop_action = [
this,&elements,&predicates,&projectedError,&targetError,&elMarked,&accumulate_improvement]
642 HBox_ptr box = elements.at(index);
643 if (_boxPtr(*box)->marked())
649 typename HBox::Container neighborhood = HBoxUtils::toContainer(HBoxUtils::markAdmissible(*box,m_m));
650 HBoxContainer neighborhoodtmp = HBoxContainer(neighborhood);
651 _setContainerProperties(neighborhood);
652 T neighborhoodImprovement = std::accumulate(neighborhood.begin(),neighborhood.end(),(T)( 0 ),accumulate_improvement);
655 if (_checkBoxes(neighborhood,predicates))
657 projectedError -= neighborhoodImprovement;
658 _addAndMark(neighborhood,elMarked);
661 return (projectedError < targetError);
664 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
665 elMarked = HBoxUtils::Unique(elMarked);
666 gsDebug<<
"[Mark projected fraction] Marked "<<elMarked.totalSize()<<
" elements with projected error = "<<projectedError<<
" and target error = "<<targetError<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
670 template<
bool _coarsen,
bool _admissible>
671 typename std::enable_if<!_coarsen && !_admissible, void>::type
672 gsAdaptiveMeshing<T>::_markProjectedFraction_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
674 gsDebug<<
"Projected fraction (not admissible) marking for refinement...\n";
675 T targetError = m_refParamExtra;
676 if (m_totalError < targetError)
678 if (m_uniformRefError > targetError)
680 this->_markFraction_impl<_coarsen,_admissible>(elements,predicates,elMarked);
683 T projectedError = m_totalError;
685 auto loop_action = [
this,&elements,&predicates,&projectedError,&targetError,&elMarked]
688 HBox_ptr box = elements.at(index);
694 if (_checkBox(*box,predicates))
696 projectedError -= box->projectedImprovement();
697 _addAndMark(*box,elMarked);
699 return (projectedError < targetError);
703 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
704 elMarked = HBoxUtils::Unique(elMarked);
705 gsDebug<<
"[Mark projected fraction] Marked "<<elMarked.totalSize()<<
" elements with projected error = "<<projectedError<<
" and target error = "<<targetError<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
709 template<
bool _coarsen,
bool _admissible>
710 typename std::enable_if< _coarsen && _admissible, void>::type
711 gsAdaptiveMeshing<T>::_markPercentage_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
713 gsDebug<<
"Percentage marking for coarsening...\n";
715 size_t NE = elements.size();
718 index_t NR = cast<T,index_t>( math::floor( m_crsParam * T(NE) ) );
721 auto loop_action = [
this,&elements,&predicates,&NR,&nmarked,&elMarked]
724 HBox * box = elements.at(index);
727 if (_boxPtr(*box)->marked() || !_checkBox(*box,predicates))
731 typename HBox::Container sibs = box->getSiblings();
732 _setContainerProperties(sibs);
733 if (!gsHBoxUtils<2,T>::allActive(sibs))
737 if (_checkBoxes(sibs,predicates))
739 nmarked += sibs.size();
740 _addAndMark(sibs,elMarked);
742 _addAndMark(*box,elMarked);
744 return (nmarked > NR);
747 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
748 elMarked = HBoxUtils::Unique(elMarked);
749 gsDebug<<
"[Mark percentage] Marked "<<elMarked.totalSize()<<
", ("<<nmarked<<
") elements ("<<(T)nmarked/NE*100<<
"%"<<
" of NE "<<NE<<
") and threshold = "<<NR<<
" ("<<m_crsParam*100<<
"%)"<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
753 template<
bool _coarsen,
bool _admissible>
754 typename std::enable_if< _coarsen && !_admissible, void>::type
755 gsAdaptiveMeshing<T>::_markPercentage_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
757 gsDebug<<
"Percentage marking for coarsening...\n";
759 size_t NE = elements.size();
762 index_t NR = cast<T,index_t>( math::floor( m_crsParam * T(NE) ) );
765 auto loop_action = [
this,&elements,&predicates,&NR,&nmarked,&elMarked]
768 HBox * box = elements.at(index);
770 if (_checkBox(*box,predicates))
773 _addAndMark(*box,elMarked);
775 return (nmarked > NR);
778 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
779 elMarked = HBoxUtils::Unique(elMarked);
780 gsDebug<<
"[Mark percentage] Marked "<<elMarked.totalSize()<<
", ("<<nmarked<<
") elements ("<<(T)nmarked/NE*100<<
"%"<<
" of NE "<<NE<<
") and threshold = "<<NR<<
" ("<<m_crsParam*100<<
"%)"<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
784 template<
bool _coarsen,
bool _admissible>
785 typename std::enable_if<!_coarsen && _admissible, void>::type
786 gsAdaptiveMeshing<T>::_markPercentage_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
788 gsDebug<<
"Percentage marking (admissible) for refinement...\n";
790 size_t NE = elements.size();
793 index_t NR = cast<T,index_t>( math::floor( m_refParam * T(NE) ) );
796 auto loop_action = [
this,&elements,&predicates,&nmarked,&NR,&elMarked]
800 HBox_ptr box = elements.at(index);
802 if (_boxPtr(*box)->marked())
805 typename HBox::Container neighborhood = HBoxUtils::toContainer(HBoxUtils::markAdmissible(*box,m_m));
806 _setContainerProperties(neighborhood);
808 if (_checkBoxes(neighborhood,predicates))
810 nmarked += neighborhood.size();
811 _addAndMark(neighborhood,elMarked);
813 return (nmarked > NR);
816 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
817 elMarked = HBoxUtils::Unique(elMarked);
818 gsDebug<<
"[Mark percentage] Marked "<<elMarked.totalSize()<<
", ("<<nmarked<<
") elements ("<<(T)nmarked/NE*100<<
"%"<<
" of NE "<<NE<<
") and threshold = "<<NR<<
" ("<<m_refParam*100<<
"%)"<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
822 template<
bool _coarsen,
bool _admissible>
823 typename std::enable_if<!_coarsen && !_admissible, void>::type
824 gsAdaptiveMeshing<T>::_markPercentage_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
826 gsDebug<<
"Percentage marking (not admissible) for refinement...\n";
828 size_t NE = elements.size();
831 index_t NR = cast<T,index_t>( math::floor( m_refParam * T(NE) ) );
834 auto loop_action = [&elements,&predicates,&NR,&nmarked,&elMarked]
837 HBox * box = elements.at(index);
839 for (
typename std::vector<gsHBoxCheck<2,T>*>::const_iterator errIt = predicates.begin(); errIt!=predicates.end(); errIt++)
840 check &= (*errIt)->check(*box);
848 return (nmarked > NR);
851 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
852 elMarked = HBoxUtils::Unique(elMarked);
853 gsDebug<<
"[Mark percentage] Marked "<<elMarked.totalSize()<<
", ("<<nmarked<<
") elements ("<<(T)nmarked/NE*100<<
"%"<<
" of NE "<<NE<<
") and threshold = "<<NR<<
" ("<<m_refParam*100<<
"%)"<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
857 T gsAdaptiveMeshing<T>::_maxError(
const boxMapType & elements)
859 auto larger_than = [](
const typename boxMapType::value_type & a,
const typename boxMapType::value_type & b)
861 return (a.second->error() < b.second->error());
865 T maxErr = (std::max_element(elements.begin(), elements.end(), larger_than ))->second->error();
871 template<
bool _coarsen,
bool _admissible>
872 typename std::enable_if< _coarsen && _admissible, void>::type
873 gsAdaptiveMeshing<T>::_markThreshold_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
875 gsDebug<<
"Threshold marking for coarsening...\n";
876 GISMO_ASSERT(m_crsParam<=1 && m_crsParam>=0,
"Coarsening parameter must be a percentage!");
878 T Thr = m_crsParam * m_maxError;
880 gsHBoxCheck<2,T> * thres_predicate =
new gsLargerErrCompare<2,T>(Thr);
882 auto loop_action = [
this,&elements,&thres_predicate,&predicates,&elMarked,¤t]
885 HBox_ptr box = elements.at(index);
887 if (thres_predicate->check(*box))
889 current = std::max(current,box->error());
894 if (_boxPtr(*box)->marked() || !_checkBox(*box,predicates))
899 typename HBox::Container sibs = box->getSiblings();
900 _setContainerProperties(sibs);
901 if (!gsHBoxUtils<2,T>::allActive(sibs))
905 if (_checkBoxes(sibs,predicates))
907 _addAndMark(sibs,elMarked);
908 _addAndMark(*box,elMarked);
913 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
914 elMarked = HBoxUtils::Unique(elMarked);
915 gsDebug<<
"[Mark threshold] Marked "<<elMarked.totalSize()<<
" elements with largest error "<<current<<
" and treshold = "<<Thr<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
919 template<
bool _coarsen,
bool _admissible>
920 typename std::enable_if< _coarsen && !_admissible, void>::type
921 gsAdaptiveMeshing<T>::_markThreshold_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
923 gsDebug<<
"Threshold marking for coarsening...\n";
924 GISMO_ASSERT(m_crsParam<=1 && m_crsParam>=0,
"Coarsening parameter must be a percentage!");
926 T Thr = m_crsParam * m_maxError;
928 gsHBoxCheck<2,T> * thres_predicate =
new gsLargerErrCompare<2,T>(Thr);
930 auto loop_action = [
this,&elements,&thres_predicate,&predicates,&elMarked,¤t]
933 HBox_ptr box = elements.at(index);
935 if (thres_predicate->check(*box))
937 current = std::max(current,box->error());
942 if (_checkBox(*box,predicates))
943 _addAndMark(*box,elMarked);
947 std::vector<index_t>::const_iterator it = std::find_if(m_crsPermutation.cbegin(),m_crsPermutation.cend(),loop_action);
948 elMarked = HBoxUtils::Unique(elMarked);
949 gsDebug<<
"[Mark threshold] Marked "<<elMarked.totalSize()<<
" elements with largest error "<<current<<
" and treshold = "<<Thr<<((it==m_crsPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
953 template<
bool _coarsen,
bool _admissible>
954 typename std::enable_if<!_coarsen && _admissible, void>::type
955 gsAdaptiveMeshing<T>::_markThreshold_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
957 gsDebug<<
"Threshold marking (admissible) for refinement...\n";
958 GISMO_ASSERT(m_refParam<=1 && m_refParam>=0,
"Refinement parameter must be a percentage!");
960 T Thr = m_refParam * m_maxError;
962 gsHBoxCheck<2,T> * thres_predicate =
new gsSmallerErrCompare<2,T>(Thr);
964 auto loop_action = [
this,&elements,&thres_predicate,&predicates,&elMarked,¤t]
967 HBox_ptr box = elements.at(index);
969 if (thres_predicate->check(*box))
971 current = std::max(current,box->error());
975 if (_boxPtr(*box)->marked())
980 typename HBox::Container neighborhood = HBoxUtils::toContainer(HBoxUtils::markAdmissible(*box,m_m));
981 _setContainerProperties(neighborhood);
984 if (_checkBoxes(neighborhood,predicates))
985 _addAndMark(neighborhood,elMarked);
989 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
990 elMarked = HBoxUtils::Unique(elMarked);
991 gsDebug<<
"[Mark threshold] Marked "<<elMarked.totalSize()<<
" elements with largest error "<<current<<
" and treshold = "<<Thr<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
995 template<
bool _coarsen,
bool _admissible>
996 typename std::enable_if<!_coarsen && !_admissible, void>::type
997 gsAdaptiveMeshing<T>::_markThreshold_impl(
const boxMapType & elements,
const std::vector<gsHBoxCheck<2,T> *> predicates,
typename gsAdaptiveMeshing<T>::HBoxContainer & elMarked)
const
999 gsDebug<<
"Threshold marking (not admissible) for refinement...\n";
1000 GISMO_ASSERT(m_refParam<=1 && m_refParam>=0,
"Refinement parameter must be a percentage!");
1002 T Thr = m_refParam * m_maxError;
1004 gsHBoxCheck<2,T> * thres_predicate =
new gsSmallerErrCompare<2,T>(Thr);
1006 auto loop_action = [
this,&elements,&thres_predicate,&predicates,&elMarked,¤t]
1009 HBox_ptr box = elements.at(index);
1011 if (thres_predicate->check(*box))
1013 current = std::max(current,box->error());
1017 if (_checkBox(*box,predicates))
1018 _addAndMark(*box,elMarked);
1023 std::vector<index_t>::const_iterator it = std::find_if(m_refPermutation.cbegin(),m_refPermutation.cend(),loop_action);
1024 elMarked = HBoxUtils::Unique(elMarked);
1025 gsDebug<<
"[Mark threshold] Marked "<<elMarked.totalSize()<<
" elements with largest error "<<current<<
" and treshold = "<<Thr<<((it==m_refPermutation.end()) ?
" (maximum number marked)" :
"")<<
"\n";
1029 void gsAdaptiveMeshing<T>::defaultOptions()
1031 m_options.addInt(
"CoarsenRule",
"Rule used for coarsening: 1=GARU, 2=PUCA, 3=BULK.",1);
1032 m_options.addInt(
"RefineRule",
"Rule used for refinement: 1=GARU, 2=PUCA, 3=BULK.",1);
1033 m_options.addReal(
"CoarsenParam",
"Parameter used for coarsening",0.1);
1034 m_options.addReal(
"RefineParam",
"Parameter used for refinement",0.1);
1035 m_options.addReal(
"CoarsenParamExtra",
"Extra parameter used for coarsening",0.1);
1036 m_options.addReal(
"RefineParamExtra",
"Extra parameter used for refinement",0.1);
1038 m_options.addInt(
"Convergence_alpha",
"Estimated convergence parameter of he error, for alpha*p+beta convergence",-1);
1039 m_options.addInt(
"Convergence_beta",
"Estimated convergence parameter of he error, for alpha*p+beta convergence",-1);
1041 m_options.addInt(
"CoarsenExtension",
"Extension coarsening",0);
1042 m_options.addInt(
"RefineExtension",
"Extension refinement",0);
1044 m_options.addInt(
"MaxLevel",
"Maximum refinement level",3);
1046 m_options.addInt(
"Admissibility",
"Admissibility region, 0=T-admissibility (default), 1=H-admissibility",0);
1047 m_options.addSwitch(
"Admissible",
"Mark the admissible region",
true);
1048 m_options.addInt(
"Jump",
"Jump parameter m",2);
1052 void gsAdaptiveMeshing<T>::getOptions()
1054 switch (m_options.askInt(
"CoarsenRule",3))
1069 GISMO_ERROR(
"Coarsening marking strategy unknown");
1073 switch (m_options.askInt(
"RefineRule",3))
1088 GISMO_ERROR(
"Refinement marking strategy unknown");
1092 m_crsParam = m_options.getReal(
"CoarsenParam");
1093 m_crsParamExtra = m_options.getReal(
"CoarsenParamExtra");
1094 m_refParam = m_options.getReal(
"RefineParam");
1095 m_refParamExtra = m_options.getReal(
"RefineParamExtra");
1097 m_crsExt = m_options.getInt(
"CoarsenExtension");
1098 m_refExt = m_options.getInt(
"RefineExtension");
1100 m_maxLvl = m_options.getInt(
"MaxLevel");
1102 m_admissible = m_options.getSwitch(
"Admissible");
1103 m_m = m_options.getInt(
"Jump");
1105 m_alpha=m_options.askInt(
"Convergence_alpha",-1);
1106 m_beta=m_options.askInt(
"Convergence_beta",-1);
1110 void gsAdaptiveMeshing<T>::container_into(
const std::vector<T> & elError, HBoxContainer & result)
1113 this->_assignErrors(m_boxes,elError);
1114 for (
typename boxMapType::iterator it = m_boxes.begin(); it!=m_boxes.end(); it++)
1115 result.add(*it->second);
1120 void gsAdaptiveMeshing<T>::markRef_into(
const std::vector<T> & elError, HBoxContainer & elMarked)
1123 this->_assignErrors(m_boxes,elError);
1124 if (m_refRule!=PBULK)
1125 m_refPermutation = this->_sortPermutation(m_boxes);
1127 m_refPermutation = this->_sortPermutationProjectedRef(m_boxes);
1135 std::reverse(m_refPermutation.begin(),m_refPermutation.end());
1137 std::vector<gsHBoxCheck<2,T> *> predicates;
1138 _refPredicates_into(predicates);
1141 _markElements<false,true>( elError, m_refRule, predicates, elMarked);
1143 _markElements<false,false>( elError, m_refRule, predicates, elMarked);
1145 for (
typename std::vector<gsHBoxCheck<2,T>*>::iterator pred=predicates.begin(); pred!=predicates.end(); pred++)
1150 void gsAdaptiveMeshing<T>::markCrs_into(
const std::vector<T> & elError,
const HBoxContainer & markedRef, HBoxContainer & elMarked)
1153 this->_assignErrors(m_boxes,elError);
1155 if (m_crsRule!=PBULK)
1156 m_crsPermutation = this->_sortPermutation(m_boxes);
1158 m_crsPermutation = this->_sortPermutationProjectedCrs(m_boxes);
1159 gsDebugVar(m_crsPermutation.size());
1161 std::vector<gsHBoxCheck<2,T> *> predicates;
1162 if (markedRef.totalSize()==0 || !m_admissible)
1163 _crsPredicates_into(predicates);
1165 _crsPredicates_into(markedRef,predicates);
1168 _markElements<true,true>( elError, m_crsRule, predicates, elMarked);
1170 _markElements<true,false>( elError, m_crsRule, predicates, elMarked);
1172 gsDebugVar(m_crsPermutation.size());
1174 for (
typename std::vector<gsHBoxCheck<2,T>*>::iterator pred=predicates.begin(); pred!=predicates.end(); pred++)
1179 void gsAdaptiveMeshing<T>::markCrs_into(
const std::vector<T> & elError, HBoxContainer & elMarked)
1181 HBoxContainer container;
1182 this->markCrs_into(elError,container,elMarked);
1186 void gsAdaptiveMeshing<T>::markRef(
const std::vector<T> & errors)
1188 markRef_into( errors, m_markedRef);
1192 void gsAdaptiveMeshing<T>::markCrs(
const std::vector<T> & errors)
1194 markCrs_into( errors, m_markedRef, m_markedCrs);
1198 bool gsAdaptiveMeshing<T>::refine(
const HBoxContainer & markedRef)
1200 bool refine = (markedRef.totalSize()>0);
1202 _refineMarkedElements(markedRef,m_refExt);
1207 bool gsAdaptiveMeshing<T>::unrefine(
const HBoxContainer & markedCrs)
1209 bool coarsen= (markedCrs.totalSize()>0);
1211 _unrefineMarkedElements(markedCrs,m_crsExt);
1216 bool gsAdaptiveMeshing<T>::refineAll()
1219 for (
typename boxMapType::iterator it = m_boxes.begin(); it!=m_boxes.end(); it++)
1220 ref.add(*it->second);
1228 bool gsAdaptiveMeshing<T>::unrefineAll()
1231 for (
typename boxMapType::iterator it = m_boxes.begin(); it!=m_boxes.end(); it++)
1232 crs.add(*it->second);
1234 this->unrefine(crs);
1252 void gsAdaptiveMeshing<T>::_refineMarkedElements(
const HBoxContainer & markedRef,
1255 gsBasis<T> * basis =
nullptr;
1257 gsMultiPatch<T> * mp;
1258 gsMultiBasis<T> * mb;
1260 for (
index_t pn=0; pn < m_input->nPieces(); ++pn )
1262 if ( (mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input)) != nullptr ) basis = &(mp->basis(pn));
1263 if ( (mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input)) != nullptr ) basis = &(mb->basis(pn));
1264 GISMO_ENSURE(basis!=
nullptr,
"Object is not gsMultiBasis or gsMultiPatch");
1296 gsHBoxContainer<2,T> container = markedRef.patch(pn);
1297 container.toUnitBoxes();
1298 if (refExtension==0)
1299 if (
nullptr != (mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input)))
1300 mp->patch(pn).refineElements( container.toRefBoxes(pn) );
1301 else if (
nullptr != (mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input)))
1302 mb->basis( pn).refineElements( container.toRefBoxes(pn) );
1304 GISMO_ERROR(
"No gsMultiPatch or gsMultiBasis found");
1306 if (
nullptr != (mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input)))
1309 std::vector<index_t> elements = mp->patch(pn).basis().asElements(container.toCoords(pn), refExtension);
1310 mp->patch(pn).refineElements( elements );
1312 else if (
nullptr != (mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input)))
1315 mb->basis( pn).refine(container.toCoords(pn), refExtension );
1318 GISMO_ERROR(
"No gsMultiPatch or gsMultiBasis found");
1325 void gsAdaptiveMeshing<T>::_unrefineMarkedElements(
const HBoxContainer & markedCrs,
1328 gsBasis<T> * basis =
nullptr;
1330 gsMultiPatch<T> * mp;
1331 gsMultiBasis<T> * mb;
1333 for (
index_t pn=0; pn < m_input->nPieces(); ++pn )
1335 if (
nullptr != (mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input)) ) basis = &(mp->basis(pn));
1336 if (
nullptr != (mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input)) ) basis = &(mb->basis(pn));
1337 GISMO_ENSURE(basis!=
nullptr,
"Object is not gsMultiBasis or gsMultiPatch");
1367 gsHBoxContainer<2,T> container = markedCrs.patch(pn);
1368 container.toUnitBoxes();
1369 if (crsExtension==0)
1370 if (
nullptr != (mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input)))
1371 mp->patch(pn).unrefineElements( container.toCrsBoxes(pn) );
1372 else if (
nullptr != (mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input)))
1373 mb->basis( pn).unrefineElements( container.toCrsBoxes(pn) );
1375 GISMO_ERROR(
"No gsMultiPatch or gsMultiBasis found");
1377 if ((mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input))!=
nullptr)
1380 std::vector<index_t> elements = mp->patch(pn).basis().asElementsUnrefine(markedCrs.toCoords(pn), crsExtension);
1381 mp->patch(pn).unrefineElements( elements );
1383 else if ((mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input))!=
nullptr)
1386 mb->unrefine( pn, markedCrs.toCoords(pn), crsExtension );
1389 GISMO_ERROR(
"No gsMultiPatch or gsMultiBasis found");
1396 typename gsAdaptiveMeshing<T>::HBoxContainer gsAdaptiveMeshing<T>::_toContainer(
const std::vector<bool> & bools)
const
1398 HBoxContainer container;
1400 #pragma omp parallel
1403 const int tid = omp_get_thread_num();
1404 const int nt = omp_get_num_threads();
1409 gsBasis<T> * basis =
nullptr;
1411 gsMultiPatch<T> * mp;
1412 gsMultiBasis<T> * mb;
1413 typename gsBasis<T>::domainIter domIt;
1414 gsHDomainIterator<T,2> * domHIt =
nullptr;
1415 for (
index_t patchInd=0; patchInd < m_input->nPieces(); ++patchInd)
1418 if ((mp =
dynamic_cast<gsMultiPatch<T>*
>(m_input))!= nullptr ) basis = &(mp->basis(patchInd));
1419 if ((mb =
dynamic_cast<gsMultiBasis<T>*
>(m_input))!= nullptr ) basis = &(mb->basis(patchInd));
1420 GISMO_ASSERT(basis!=
nullptr,
"Object is not gsMultiBasis or gsMultiPatch");
1422 domIt = basis->makeDomainIterator();
1423 domHIt =
dynamic_cast<gsHDomainIterator<T,2> *
>(domIt.get());
1424 GISMO_ENSURE(domHIt!=
nullptr,
"Domain should be hierarchical");
1427 c = patch_cnt + tid;
1428 patch_cnt += domHIt->numElements();
1429 for ( domHIt->next(tid); domHIt->good(); domHIt->next(nt) )
1431 for (; domHIt->good(); domHIt->next() )
1435 #pragma omp critical (gsAdaptiveMeshingtoContainer)
1436 container.add(HBox(domHIt,patchInd));
1451 index_t gsAdaptiveMeshing<T>::numBlocked()
const
1453 gsMaxLvlCompare<2,T> comp(m_maxLvl);
1455 for (
typename boxMapType::const_iterator it=m_boxes.cbegin(); it!=m_boxes.cend(); it++)
1456 numBlocked += comp.check(*it->second);
1462 index_t gsAdaptiveMeshing<T>::numElements()
const
1464 return m_indices.size();
1468 void gsAdaptiveMeshing<T>::assignErrors(
const std::vector<T> & elError)
1470 this->_assignErrors(m_boxes,elError);
1474 T gsAdaptiveMeshing<T>::blockedError()
const
1476 gsMaxLvlCompare<2,T> comp(m_maxLvl);
1478 for (
typename boxMapType::const_iterator it=m_boxes.cbegin(); it!=m_boxes.cend(); it++)
1480 if (!(comp.check(*it->second)))
1481 error += it->second->error();
1488 T gsAdaptiveMeshing<T>::nonBlockedError()
const
1490 gsMaxLvlCompare<2,T> comp(m_maxLvl);
1492 for (
typename boxMapType::const_iterator it=m_boxes.cbegin(); it!=m_boxes.cend(); it++)
1494 if (comp.check(*it->second))
1495 error += it->second->error();
#define GISMO_NO_IMPLEMENTATION
Definition: gsDebug.h:129
#define gsDebug
Definition: gsDebug.h:61
#define index_t
Definition: gsConfig.h:32
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
Provides declaration of THBSplineBasis class.
Base class for performing checks on gsHBox objects.
Definition: gsAdaptiveMeshingCompare.h:31
Checks if the coarsening neighborhood of a box is empty and if it overlaps with a refinement mask...
Definition: gsAdaptiveMeshingCompare.h:134
#define GISMO_UNUSED(x)
Definition: gsDebug.h:112
#define GISMO_ERROR(message)
Definition: gsDebug.h:118
void _markElements(const std::vector< T > &elError, const index_t refCriterion, const std::vector< gsHBoxCheck< 2, T > * > &predicates, HBoxContainer &elMarked) const
Marks elements/cells for refinement.
Definition: gsAdaptiveMeshing.hpp:201
Provides adaptive meshing routines.
Definition: gsAdaptiveMeshing.h:41
Provides declaration of HBSplineBasis class.
Checks if the level of a gsHBox is bigger than a minimum level.
Definition: gsAdaptiveMeshingCompare.h:46