28 using face_bitset = mesh_region::face_bitset;
30 mesh_region::mesh_region(
const mesh_region &other)
31 : p(std::make_shared<impl>()), id_(
size_type(-2)), parent_mesh(0) {
32 this->operator=(other);
35 mesh_region::mesh_region()
37 partitioning_allowed{true}, parent_mesh(nullptr){
39 mark_region_changed();
43 partitioning_allowed{true}, parent_mesh(nullptr){
44 mark_region_changed();
48 p(std::make_shared<impl>()), id_(id__), type_(type),
49 partitioning_allowed{true}, parent_mesh(&m){
51 mark_region_changed();
54 mesh_region::mesh_region(
const dal::bit_vector &bv)
56 partitioning_allowed{true}, parent_mesh(nullptr){
59 mark_region_changed();
62 void mesh_region::mark_region_changed()
const{
63 index_updated.all_threads() =
false;
64 partitions_updated.all_threads() =
false;
65 serial_index_updated =
false;
68 void mesh_region::touch_parent_mesh(){
69 if (parent_mesh) parent_mesh->touch_from_region(id_);
78 r->p = std::make_shared<impl>();
86 mark_region_changed();
91 if (!parent_mesh && !from.parent_mesh){
94 partitioning_allowed.store(from.partitioning_allowed.load());
96 if (!p) p = std::make_shared<impl>();
101 else if (!parent_mesh) {
105 parent_mesh = from.parent_mesh;
106 partitioning_allowed.store(from.partitioning_allowed.load());
111 type_= from.get_type();
112 partitioning_allowed.store(from.partitioning_allowed.load());
118 partitioning_allowed =
true;
122 mark_region_changed();
126 bool mesh_region::compare(
const mesh &m1,
127 const mesh_region &mr,
128 const mesh &m2)
const {
129 if (&m1 != &m2)
return false;
130 if (!p && !mr.p)
return (id_ == mr.id_);
133 if (p && !(mr.p))
return false;
134 if (!p && mr.p)
return false;
136 if (p->m != mr.p->m)
return false;
140 face_bitset mesh_region::operator[](
size_t cv)
const{
141 auto it = rp().m.find(cv);
142 if (it != rp().m.end())
return it->second;
146 void mesh_region::update_partition_iterators()
const{
147 if ((partitions_updated.thrd_cast() ==
true))
return;
148 itbegin = partition_begin();
149 itend = partition_end ();
150 partitions_updated =
true;
152 mesh_region::const_iterator
153 mesh_region::partition_begin( )
const{
154 auto region_size = rp().m.size();
155 if (region_size < partitions_updated.num_threads()){
157 if (partitions_updated.this_thread() == 0)
return rp().m.begin();
158 else return rp().m.end();
160 auto partition_size =
static_cast<size_type>
161 (std::ceil(
static_cast<scalar_type
>(region_size)/
162 static_cast<scalar_type
>(partitions_updated.num_threads())));
163 auto index_begin = partition_size * partitions_updated.this_thread();
164 if (index_begin >= region_size )
return rp().m.end();
166 auto it = rp().m.begin();
167 for (
size_type i = 0; i != index_begin; ++i) ++it;
171 mesh_region::const_iterator
172 mesh_region::partition_end( )
const{
173 auto region_size = rp().m.size();
174 if (region_size< partitions_updated.num_threads())
return rp().m.end();
176 auto partition_size =
static_cast<size_type>
177 (std::ceil(
static_cast<scalar_type
>(region_size)/
178 static_cast<scalar_type
>(partitions_updated.num_threads())));
179 auto index_end = partition_size * (partitions_updated.this_thread() + 1);
180 if (index_end >= region_size )
return rp().m.end();
182 auto it = rp().m.begin();
183 for (
size_type i = 0; i < index_end && it != rp().m.end(); ++i) ++it;
187 mesh_region::const_iterator mesh_region::begin()
const{
188 GMM_ASSERT1(p != 0,
"Internal error");
190 update_partition_iterators();
193 else return rp().m.begin();
196 mesh_region::const_iterator mesh_region::end()
const{
198 update_partition_iterators();
201 else return rp().m.end();
205 partitioning_allowed =
true;
209 auto &
mesh = *get_parent_mesh();
210 for (
auto &&cv : dal::bv_iterable_c{
index()}) {
211 for (
const auto &pt :
mesh.points_of_convex(cv)) {
212 for (
auto j = 0; j != Pmin.size(); ++j){
213 Pmin[j] = std::min(Pmin[j], pt[j]);
214 Pmax[j] = std::max(Pmax[j], pt[j]);
221 partitioning_allowed =
false;
224 bool mesh_region::is_partitioning_allowed()
const{
225 return partitioning_allowed;
228 void mesh_region::update_index()
const{
230 rp().index_.thrd_cast() : rp().serial_index_;
231 if (convex_index.card() != 0) convex_index.clear();
232 for (
auto &&pair : *
this){
233 if (pair.second.any()) convex_index.add(pair.first);
238 GMM_ASSERT1(p,
"Use from_mesh on that region before");
240 if (!(index_updated.thrd_cast() ==
true)){
242 index_updated =
true;
247 if (!serial_index_updated){
249 serial_index_updated =
true;
251 return rp().serial_index_;
255 void mesh_region::add(
const dal::bit_vector &bv){
256 for (dal::bv_visitor i(bv); !i.finished(); ++i){
260 mark_region_changed();
266 mark_region_changed();
270 auto it = wp().m.find(cv);
271 if (it != wp().m.end()){
274 mark_region_changed();
279 auto it = wp().m.find(cv);
280 if (it != wp().m.end()) {
282 if (it->second.none()) wp().m.erase(it);
284 mark_region_changed();
288 void mesh_region::clear(){
291 mark_region_changed();
294 void mesh_region::clean(){
295 for (map_t::iterator it = wp().m.begin(), itn;
296 it != wp().m.end(); it = itn) {
299 if (!(*it).second.any()) wp().m.erase(it);
302 mark_region_changed();
306 auto it1 = wp().m.find(cv1);
307 auto it2 = wp().m.find(cv2);
308 auto ite = wp().m.end();
311 if (it1 != ite) f1 = it1->second;
312 if (it2 != ite) f2 = it2->second;
313 if (!f1.none()) wp().m[cv2] = f1;
314 else if (it2 != ite) wp().m.erase(it2);
315 if (!f2.none()) wp().m[cv1] = f2;
316 else if (it1 != ite) wp().m.erase(it1);
318 mark_region_changed();
322 GMM_ASSERT1(p,
"Use from mesh on that region before");
323 auto it = rp().m.find(cv);
324 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
return false;
330 auto it = rp().m.find(cv);
331 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
337 else return m.region(
id()).is_in(cv, f);
341 bool mesh_region::is_empty()
const{
342 return rp().m.empty();
347 (or_mask()[0] ==
true && or_mask().count() == 1);
351 return (
id() !=
size_type(-1)) && (is_empty() || (and_mask()[0] ==
false));
354 face_bitset mesh_region::faces_of_convex(
size_type cv)
const{
355 auto it = rp().m.find(cv);
356 if (it != rp().m.end())
return ((*it).second) >> 1;
357 else return face_bitset();
360 face_bitset mesh_region::and_mask()
const{
362 if (rp().m.empty())
return bs;
364 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
365 if ( (*it).second.any() ) bs &= (*it).second;
369 face_bitset mesh_region::or_mask()
const{
371 if (rp().m.empty())
return bs;
372 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
373 if ( (*it).second.any() ) bs |= (*it).second;
379 for (
auto it = begin(); it != end(); ++it)
380 sz += (*it).second.count();
384 size_type mesh_region::unpartitioned_size()
const{
386 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
387 sz += (*it).second.count();
393 GMM_TRACE4(
"intersection of "<<a.id()<<
" and "<<b.id());
400 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
401 "are not supported for set operations");
403 for (const_iterator it = b.begin();it != b.end(); ++it) r.wp().m.insert(*it);
407 for (const_iterator it = a.begin();it != a.end(); ++it) r.wp().m.insert(*it);
411 auto ita = a.begin(), enda = a.end(),
412 itb = b.begin(), endb = b.end();
414 while (ita != enda && itb != endb) {
415 if (ita->first < itb->first) ++ita;
416 else if (ita->first > itb->first) ++itb;
418 face_bitset maska = ita->second, maskb = itb->second, bs;
419 if (maska[0] && !maskb[0]) bs = maskb;
420 else if (maskb[0] && !maska[0]) bs = maska;
421 else bs = maska & maskb;
422 if (bs.any()) r.wp().m.insert(r.wp().m.end(), std::make_pair(ita->first,bs));
431 GMM_TRACE4(
"Merger of " << a.id() <<
" and " << b.id());
434 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
435 "are not supported for set operations");
436 for (
auto it = a.begin();it != a.end(); ++it){
437 r.wp().m.insert(*it);
439 for (
auto it = b.begin();it != b.end(); ++it){
440 r.wp().m[it->first] |= it->second;
448 GMM_TRACE4(
"subtraction of "<<a.id()<<
" and "<<b.id());
451 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
452 "are not supported for set operations");
453 for (
auto ita = a.begin();ita != a.end(); ++ita)
454 r.wp().m.insert(*ita);
456 for (
auto itb = b.begin();itb != b.end(); ++itb){
457 auto cv = itb->first;
458 auto it = r.wp().m.find(cv);
459 if (it != r.wp().m.end()){
460 it->second &= ~(itb->second);
461 if (it->second.none()) r.wp().m.erase(it);
470 if (&m1 != &m2)
return 0;
471 int r = 1, partially = 0;
472 for (
mr_visitor cv(*
this, m1); !cv.finished(); cv.next())
473 if (cv.is_face() && rg2.is_in(cv.cv(),
short_type(-1), m2))
477 return r == 1 ? 1 : partially;
481 return m.regions_index().last_true()+1;
484 void mesh_region::error_if_not_faces()
const{
485 GMM_ASSERT1(
is_only_faces(),
"Expecting a set of faces, not convexes");
488 void mesh_region::error_if_not_convexes()
const{
492 void mesh_region::error_if_not_homogeneous()
const{
494 "of convexes or a set of faces, but not a mixed set");
498 #if GETFEM_PARA_LEVEL > 1
500 mesh_region::visitor::visitor(
const mesh_region &s,
const mesh &m,
501 bool intersect_with_mpi) :
509 if (intersect_with_mpi)
510 init(m.get_mpi_region());
512 init(m.convex_index());
513 }
else if (s.id() ==
size_type(-2) && s.p.get()) {
514 if (intersect_with_mpi) {
515 mpi_rg = std::make_unique<mesh_region>(s);
516 mpi_rg->from_mesh(m);
517 m.intersect_with_mpi_region(*mpi_rg);
522 GMM_ASSERT1(s.id() !=
size_type(-2),
"Internal error");
523 if (intersect_with_mpi)
524 init(m.get_mpi_sub_region(s.id()));
526 init(m.region(s.id()));
533 mesh_region::visitor::visitor(
const mesh_region &s,
const mesh &m,
bool)
541 init(m.convex_index());
542 }
else if (s.id() ==
size_type(-2) && s.p.get()) {
545 GMM_ASSERT1(s.id() !=
size_type(-2),
"Internal error");
546 init(m.region(s.id()));
553 bool mesh_region::visitor::next(){
563 while (itb != iteb && !(*itb)) ++itb;
567 if (it == ite) { finished_=
true;
return false; }
572 if (c.none())
continue;
578 mesh_region::visitor::visitor(
const mesh_region &s) :
583 void mesh_region::visitor::init(
const dal::bit_vector &bv){
585 itb = bv.begin(); iteb = bv.end();
586 while (itb != iteb && !(*itb)) ++itb;
590 void mesh_region::visitor::init(
const mesh_region &s){
597 std::ostream & operator <<(std::ostream &os,
const mesh_region &w){
599 os <<
" ALL_CONVEXES";
601 for (mr_visitor cv(w); !cv.finished(); cv.next()){
603 if (cv.is_face()) os <<
"/" << cv.f();
608 os <<
" region " << w.id();
613 struct dummy_mesh_region_{
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
static T & instance()
Instance from the current thread.
"iterator" class for regions.
structure used to hold a set of convexes and/or convex faces.
static mesh_region merge(const mesh_region &a, const mesh_region &b)
return the union of two mesh_regions
const mesh_region & from_mesh(const mesh &m) const
For regions which have been built with just a number 'id', from_mesh(m) sets the current region to 'm...
void allow_partitioning()
In multithreaded part of the program makes only a partition of the region visible in the index() and ...
size_type size() const
Region size, or the size of the region partition on the current thread if the region is partitioned.
void prohibit_partitioning()
Disregard partitioning, which means being able to see the whole region in multithreaded code.
bool is_only_faces() const
Return true if the region do contain only convex faces.
int region_is_faces_of(const getfem::mesh &m1, const mesh_region &rg2, const getfem::mesh &m2) const
Test if the region is a boundary of a list of faces of elements of region rg.
static mesh_region intersection(const mesh_region &a, const mesh_region &b)
return the intersection of two mesh regions
void bounding_box(base_node &Pmin, base_node &Pmax) const
Return the bounding box [Pmin - Pmax] of the mesh_region.
bool is_only_convexes() const
Return true if the region do not contain any convex face.
const dal::bit_vector & index() const
Index of the region convexes, or the convexes from the partition on the current thread.
static size_type free_region_id(const getfem::mesh &m)
Extract the next region number that does not yet exists in the mesh.
static mesh_region subtract(const mesh_region &a, const mesh_region &b)
subtract the second region from the first one
Describe a mesh (collection of convexes (elements) and points).
const mesh_region region(size_type id) const
Return the region of index 'id'.
Define a getfem::getfem_mesh object.
region objects (set of convexes and/or convex faces)
Tools for multithreaded, OpenMP and Boost based parallelization.
gmm::uint16_type short_type
used as the common short type integer in the library
size_t size_type
used as the common size type in the library
GEneric Tool for Finite Element Methods.
bool me_is_multithreaded_now()
is the program running in the parallel section
const mesh_region & dummy_mesh_region()
Dummy mesh_region for default parameter of functions.