30 #ifndef FEELPP_ELEMENTS_HPP
31 #define FEELPP_ELEMENTS_HPP 1
34 #include <boost/multi_index_container.hpp>
35 #include <boost/multi_index/member.hpp>
36 #include <boost/multi_index/composite_key.hpp>
37 #include <boost/multi_index/mem_fun.hpp>
38 #include <boost/multi_index/ordered_index.hpp>
39 #include <boost/multi_index/hashed_index.hpp>
40 #include <boost/multi_index/random_access_index.hpp>
42 #include <feel/feelmesh/geoelement.hpp>
47 namespace multi_index = boost::multi_index;
52 template <
typename EltType >
54 updateElementGhostConnectEdgeToElement( EltType& e,
int i, mpl::int_<1> )
56 template <
typename EltType >
58 updateElementGhostConnectEdgeToElement( EltType& e,
int i, mpl::int_<2> )
60 template <
typename EltType >
62 updateElementGhostConnectEdgeToElement( EltType& e,
int i, mpl::int_<3> )
64 e.edge( i ).addElementGhost( e.processId(),e.id() );
76 template<
typename ElementType>
91 typedef typename mpl::if_<mpl::equal_to<mpl::int_<ElementType::nDim>, mpl::int_<3> >,
92 mpl::identity<GeoElement3D<ElementType::nRealDim, ElementType> >,
93 typename mpl::if_<mpl::equal_to<mpl::int_<ElementType::nDim>, mpl::int_<2> >,
94 mpl::identity<GeoElement2D<ElementType::nRealDim, ElementType> >,
95 typename mpl::if_<mpl::equal_to<mpl::int_<ElementType::nDim>, mpl::int_<1> >,
96 mpl::identity<GeoElement1D<ElementType::nRealDim, ElementType> >,
97 mpl::identity<GeoElement0D<ElementType::nRealDim, ElementType> > >::type>::type>::type::type element_type;
102 typedef multi_index::multi_index_container<
104 multi_index::indexed_by<
107 multi_index::ordered_unique<
108 multi_index::composite_key<element_type,
109 multi_index::const_mem_fun<element_type,
111 &element_type::processId>,
112 multi_index::const_mem_fun<element_type,
114 &element_type::id> > >,
116 multi_index::ordered_non_unique<multi_index::tag<detail::by_marker>,
117 multi_index::composite_key<element_type,
118 multi_index::const_mem_fun<element_type,
120 &element_type::marker>,
121 multi_index::const_mem_fun<element_type,
123 &element_type::processId> > >,
125 multi_index::ordered_non_unique<multi_index::tag<detail::by_marker2>,
126 multi_index::composite_key<element_type,
127 multi_index::const_mem_fun<element_type,
129 &element_type::marker2>,
130 multi_index::const_mem_fun<element_type,
132 &element_type::processId> > >,
135 multi_index::ordered_non_unique<multi_index::tag<detail::by_marker3>,
136 multi_index::composite_key<element_type,
137 multi_index::const_mem_fun<element_type,
139 &element_type::marker3>,
140 multi_index::const_mem_fun<element_type,
142 &element_type::processId> > >,
145 multi_index::ordered_non_unique<multi_index::tag<detail::by_location>,
146 multi_index::composite_key<element_type,
147 multi_index::const_mem_fun<element_type,
149 &element_type::processId>,
150 multi_index::const_mem_fun<element_type,
152 &element_type::isOnBoundary>,
153 multi_index::const_mem_fun<element_type,
155 &element_type::boundaryEntityDimension> > >,
159 multi_index::ordered_non_unique<multi_index::tag<detail::by_pid>,
160 multi_index::const_mem_fun<element_type,
162 &element_type::processId> >,
165 multi_index::ordered_non_unique<multi_index::tag<detail::by_ghostcell>,
166 multi_index::const_mem_fun<element_type,
168 &element_type::isGhostCell> >
174 typedef typename elements_type::iterator element_iterator;
175 typedef typename elements_type::const_iterator element_const_iterator;
178 typedef typename elements_type::template index<detail::by_marker>::type marker_elements;
179 typedef typename marker_elements::iterator marker_element_iterator;
180 typedef typename marker_elements::const_iterator marker_element_const_iterator;
183 typedef typename elements_type::template index<detail::by_marker2>::type marker2_elements;
184 typedef typename marker2_elements::iterator marker2_element_iterator;
185 typedef typename marker2_elements::const_iterator marker2_element_const_iterator;
188 typedef typename elements_type::template index<detail::by_marker3>::type marker3_elements;
189 typedef typename marker3_elements::iterator marker3_element_iterator;
190 typedef typename marker3_elements::const_iterator marker3_element_const_iterator;
192 typedef typename elements_type::template index<detail::by_pid>::type pid_elements;
193 typedef typename pid_elements::iterator pid_element_iterator;
194 typedef typename pid_elements::const_iterator pid_element_const_iterator;
197 typedef typename elements_type::template index<detail::by_location>::type location_elements;
198 typedef typename location_elements::iterator location_element_iterator;
199 typedef typename location_elements::const_iterator location_element_const_iterator;
201 typedef typename elements_type::template index<detail::by_ghostcell>::type ghostcell_elements;
202 typedef typename ghostcell_elements::iterator ghostcell_element_iterator;
203 typedef typename ghostcell_elements::const_iterator ghostcell_element_const_iterator;
205 typedef std::map<int, size_type> parts_map_type;
206 typedef typename parts_map_type::const_iterator parts_const_iterator_type;
209 struct update_element_neighbor_type
211 update_element_neighbor_type( uint16_type n,
size_type id )
217 void operator()( element_type& e )
219 e.setNeighbor( M_pos_neigh, M_neigh_id );
223 uint16_type M_pos_neigh;
235 struct ElementUpdatePoint
241 ElementUpdatePoint( uint16_type index,
typename element_type::PointType
const& pt )
251 void operator()( element_type& e )
253 e.setPoint( M_index, M_pt );
257 typename element_type::PointType
const& M_pt;
265 struct ElementConnectPointToElement
267 void operator()( element_type& e )
269 for (
int i = 0; i < e.numPoints; ++i )
270 e.point( i ).addElement( e.id() );
279 struct ElementGhostConnectPointToElement
281 void operator()( element_type& e )
283 for (
int i = 0; i < e.numPoints; ++i )
284 e.point( i ).addElementGhost( e.processId(),e.id() );
293 struct ElementGhostConnectEdgeToElement
295 void operator()( element_type& e )
297 for (
int i = 0; i < e.numEdges; ++i )
298 detail::updateElementGhostConnectEdgeToElement(e,i,mpl::int_<element_type::nDim>());
311 Elements( WorldComm
const& worldComm = Environment::worldComm() )
313 M_worldCommElements(worldComm),
317 Elements( Elements
const & f )
319 M_worldCommElements( f.worldCommElements() ),
320 M_elements( f.M_elements )
339 M_worldCommElements = e.M_worldCommElements;
340 M_elements = e.M_elements;
373 return M_elements.empty();
376 WorldComm
const& worldCommElements()
const
378 return M_worldCommElements;
382 bool isBoundaryElement( element_type
const & e )
const
384 return M_elements.find( e )->isOnBoundary();
386 bool isBoundaryElement(
size_type const &
id )
const
388 return M_elements.find( element_type(
id ) )->isOnBoundary();
391 element_iterator elementIterator(
size_type i )
const
393 return M_elements.template get<0>().find( boost::make_tuple( this->worldCommElements().localRank(), i ) );
398 return M_elements.template get<0>().find( boost::make_tuple( p, i ) );
401 element_type
const& element(
size_type i )
const
403 return *M_elements.template get<0>().find( boost::make_tuple( this->worldCommElements().localRank(), i ) );
408 return *M_elements.template get<0>().find( boost::make_tuple( p, i ) );
416 return M_elements.template get<0>().find( boost::make_tuple( this->worldCommElements().localRank(), i ) ) !=
417 M_elements.template get<0>().end();
420 element_iterator beginElement()
422 return M_elements.begin();
424 element_const_iterator beginElement()
const
426 return M_elements.begin();
428 element_iterator endElement()
430 return M_elements.end();
432 element_const_iterator endElement()
const
434 return M_elements.end();
438 parts_const_iterator_type beginParts()
const
440 return M_parts.begin();
442 parts_const_iterator_type endParts()
const
444 return M_parts.end();
451 std::pair<element_iterator, element_iterator>
454 return std::make_pair( M_elements.begin(), M_elements.end() );
461 std::pair<element_const_iterator, element_const_iterator>
464 return std::make_pair( M_elements.begin(), M_elements.end() );
467 element_iterator beginElementWithId(
size_type m )
469 return M_elements.template get<0>().lower_bound( boost::make_tuple( this->worldCommElements().localRank(), m ) );
471 element_const_iterator beginElementWithId(
size_type m )
const
473 return M_elements.template get<0>().lower_bound( boost::make_tuple( this->worldCommElements().localRank(), m ) );
475 element_iterator endElementWithId(
size_type m )
477 return M_elements.template get<0>().upper_bound( boost::make_tuple( this->worldCommElements().localRank(), m ) );
479 element_const_iterator endElementWithId(
size_type m )
const
481 return M_elements.template get<0>().upper_bound( boost::make_tuple( this->worldCommElements().localRank(), m ) );
489 return M_elements.template get<detail::by_marker>().equal_range( boost::make_tuple( Marker1( m ), this->worldCommElements().localRank() ) ).first;
497 return M_elements.template get<detail::by_marker2>().equal_range( boost::make_tuple( Marker2( m ), this->worldCommElements().localRank() ) ).first;
505 return M_elements.template get<detail::by_marker3>().equal_range( boost::make_tuple( Marker3( m ), this->worldCommElements().localRank() ) ).first;
513 return M_elements.template get<detail::by_marker>().equal_range( boost::make_tuple( Marker1( m ), this->worldCommElements().localRank() ) ).second;
521 return M_elements.template get<detail::by_marker2>().equal_range( boost::make_tuple( Marker2( m ), this->worldCommElements().localRank() ) ).second;
529 return M_elements.template get<detail::by_marker3>().equal_range( boost::make_tuple( Marker3( m ), this->worldCommElements().localRank() ) ).second;
536 std::pair<marker_element_const_iterator, marker_element_const_iterator>
539 return M_elements.template get<detail::by_marker>().equal_range( boost::make_tuple( Marker1( m ), this->worldCommElements().localRank() ) );
547 std::pair<marker2_element_const_iterator, marker2_element_const_iterator>
550 return M_elements.template get<detail::by_marker2>().equal_range( boost::make_tuple( Marker2( m ), this->worldCommElements().localRank() ) );
557 std::pair<marker3_element_const_iterator, marker3_element_const_iterator>
560 return M_elements.template get<detail::by_marker3>().equal_range( boost::make_tuple( Marker3( m ), this->worldCommElements().localRank() ) );
563 element_iterator beginElementWithProcessId(
size_type m )
565 return M_elements.template get<0>().lower_bound( boost::make_tuple( m ) );
567 element_const_iterator beginElementWithProcessId(
size_type m )
const
569 return M_elements.template get<0>().lower_bound( boost::make_tuple( m ) );
571 element_iterator endElementWithProcessId(
size_type m )
573 return M_elements.template get<0>().upper_bound( boost::make_tuple( m ) );
575 element_const_iterator endElementWithProcessId(
size_type m )
const
577 return M_elements.template get<0>().upper_bound( boost::make_tuple( m ) );
580 std::pair<element_const_iterator, element_const_iterator>
581 elementsWithProcessId(
size_type m )
const
583 return M_elements.template get<0>().equal_range( boost::make_tuple( m ) );
586 std::pair<element_iterator, element_iterator>
589 return M_elements.template get<0>().equal_range( boost::make_tuple( m ) );
598 typename elements_type::template nth_index<0>::type &
601 return M_elements.template get<0>();
610 typename elements_type::template nth_index<0>::type
const&
613 return M_elements.template get<0>();
625 return M_elements.template get<detail::by_marker>();
637 return M_elements.template get<detail::by_marker2>();
649 return M_elements.template get<detail::by_marker3>();
658 marker_elements
const&
661 return M_elements.template get<detail::by_marker>();
670 marker2_elements
const&
673 return M_elements.template get<detail::by_marker2>();
682 marker3_elements
const&
685 return M_elements.template get<detail::by_marker3>();
697 return M_elements.template get<detail::by_pid>();
709 return M_elements.template get<detail::by_pid>();
716 std::pair<location_element_const_iterator, location_element_const_iterator>
719 auto lower = M_elements.template get<detail::by_location>().lower_bound( boost::make_tuple( this->worldCommElements().localRank(),
bool(ON_BOUNDARY), entity_min_dim ) );
720 auto upper = M_elements.template get<detail::by_location>().upper_bound( boost::make_tuple( this->worldCommElements().localRank(), bool(ON_BOUNDARY), entity_max_dim ) );
721 return std::make_pair( lower, upper );
729 std::pair<location_element_const_iterator, location_element_const_iterator>
744 std::pair<location_element_const_iterator, location_element_const_iterator>
747 return M_elements.template get<detail::by_location>().equal_range( boost::make_tuple( this->worldCommElements().localRank(),
bool(INTERNAL),
invalid_uint16_type_value ) );
760 return M_elements.template get<detail::by_location>();
769 location_elements
const&
772 return M_elements.template get<detail::by_location>();
782 return M_elements.template get<detail::by_location>().equal_range( boost::make_tuple( this->worldCommElements().localRank(). INTERNAL,
invalid_uint16_type_value ) ).first;
791 return M_elements.template get<detail::by_location>().equal_range( boost::make_tuple( this->worldCommElements().localRank(), INTERNAL,
invalid_uint16_type_value ) ).second;
801 return M_elements.template get<detail::by_location>().equal_range( boost::make_tuple( this->worldCommElements().localRank(), INTERNAL,
invalid_uint16_type_value ) ).first;
811 return M_elements.template get<detail::by_location>().equal_range( boost::make_tuple( this->worldCommElements().localRank(), INTERNAL,
invalid_uint16_type_value ) ).second;
821 return M_elements.template get<detail::by_location>().lower_bound( boost::make_tuple( this->worldCommElements().localRank(), ON_BOUNDARY, 0 ) );
830 return M_elements.template get<detail::by_location>().upper_bound( boost::make_tuple( this->worldCommElements().localRank(), ON_BOUNDARY, 2 ) );
840 return M_elements.template get<detail::by_location>().lower_bound( boost::make_tuple( this->worldCommElements().localRank(), ON_BOUNDARY, 0 ) );
850 return M_elements.template get<detail::by_location>().upper_bound( boost::make_tuple( this->worldCommElements().localRank(), ON_BOUNDARY, 2 ) );
861 return M_elements.template get<detail::by_ghostcell>().equal_range(
true ).first;
873 return M_elements.template get<detail::by_ghostcell>().equal_range(
true ).second;
885 return M_elements.template get<detail::by_ghostcell>().equal_range(
true ).first;
897 return M_elements.template get<detail::by_ghostcell>().equal_range(
true ).second;
923 M_parts[f.marker().value()]++;
924 f.setId( M_elements.size() );
925 return *M_elements.insert( f ).first;
931 template<
typename ElementVecType>
932 void updateMarker2( ElementVecType
const& evec )
936 boost::tie( it, en ) = elementsWithProcessId( this->worldCommElements().localRank() );
938 for ( ; it != en; ++it )
939 M_elements.modify( it, [&evec]( element_type& e )
941 e.setMarker2( evec.localToGlobal( e.id(), 0, 0 ) );
945 template<
typename ElementVecType>
946 void updateMarker3( ElementVecType
const& evec )
950 boost::tie( it, en ) = elementsWithProcessId( this->worldCommElements().localRank() );
952 for ( ; it != en; ++it )
953 M_elements.modify( it, [&evec]( element_type& e )
955 e.setMarker3( evec.localToGlobal( e.id(), 0, 0 ) );
959 template<
typename IteratorRange>
960 void updateMarker2WithRangeElements( IteratorRange
const& range, flag_type flag )
962 typedef typename boost::tuples::template element<1, IteratorRange>::type iterator_range_type;
963 iterator_range_type it, en;
964 boost::tie( boost::tuples::ignore, it, en ) = range;
966 for ( ; it != en; ++it )
967 M_elements.modify( this->elementIterator( it->id() ), [&flag]( element_type& e )
969 e.setMarker2( flag );
973 template<
typename IteratorRange>
974 void updateMarker3WithRangeElements( IteratorRange
const& range, flag_type flag )
976 typedef typename boost::tuples::template element<1, IteratorRange>::type iterator_type;
977 iterator_type it, en;
978 boost::tie( boost::tuples::ignore, it, en ) = range;
980 for ( ; it != en; ++it )
981 M_elements.modify( this->elementIterator( it->id() ), [&flag]( element_type& e )
983 e.setMarker3( flag );
996 auto it = beginElement(), en = endElement();
998 for ( ; it != en; ++it )
999 M_elements.modify( it,
1000 []( element_type& e )
1002 int newtag2=0, newtag3=0;
1003 for (uint16_type f=0;f<e.numTopologicalFaces; ++f)
1005 int tag2 = e.face(f).marker2().value();
1006 int tag3 = e.face(f).marker3().value();
1007 if (tag2>0) newtag2=tag2;
1008 if (tag3>0) newtag3=tag3;
1011 if (newtag2>0) e.setMarker2( newtag2 );
1012 if (newtag3>0) e.setMarker3( newtag3 );
1020 void setWorldCommElements( WorldComm
const& _worldComm )
1022 M_worldCommElements = _worldComm;
1029 friend class boost::serialization::access;
1030 template<
class Archive>
1031 void serialize( Archive & ar,
const unsigned int version )
1039 WorldComm M_worldCommElements;
1040 elements_type M_elements;
1041 parts_map_type M_parts;