27 typedef mesh_region::face_bitset face_bitset;
29 mesh_region::mesh_region(
const mesh_region &other)
30 : p(
std::make_shared<impl>()), id_(
size_type(-2)), parent_mesh(0),
33 this->operator=(other);
37 mesh_region::mesh_region() : p(
std::make_shared<impl>()), id_(
size_type(-2)),
39 partitioning_allowed(true), parent_mesh(0), index_updated(false)
41 if (me_is_multithreaded_now()) prohibit_partitioning();
45 partitioning_allowed(true), parent_mesh(0), index_updated(false)
49 p(
std::make_shared<impl>()), id_(id__), type_(type), partitioning_allowed(true), parent_mesh(&m),
55 mesh_region::mesh_region(
const dal::bit_vector &bv) :
57 partitioning_allowed(true), parent_mesh(0), index_updated(false)
63 void mesh_region::touch_parent_mesh()
65 if (parent_mesh) parent_mesh->touch_from_region(id_);
75 r->p = std::make_shared<impl>();
83 index_updated =
false;
89 if (!this->parent_mesh && !from.parent_mesh)
92 this->type_ = from.type_;
93 this->partitioning_allowed = from.partitioning_allowed;
95 if (!this->p.get()) this->p = std::make_shared<impl>();
96 this->wp() = from.rp();
101 else if (!this->parent_mesh) {
103 this->id_ = from.id_;
104 this->type_ = from.type_;
105 this->parent_mesh = from.parent_mesh;
106 this->partitioning_allowed = from.partitioning_allowed;
111 this->wp() = from.rp();
112 this->type_= from.get_type();
113 this->partitioning_allowed = from.partitioning_allowed;
119 this->partitioning_allowed =
true;
123 index_updated =
false;
128 const mesh &m2)
const {
129 if (&m1 != &m2)
return false;
130 if (!p.get() && !mr.p.get())
return (id_ == mr.id_);
133 if (this->p.get() && !(mr.p.get()))
return false;
134 if (!(this->p.get()) && (mr.p.get()))
return false;
136 if (this->p.get()->m != mr.p.get()->m)
return false;
140 face_bitset mesh_region::operator[](
size_t cv)
const 142 map_t::const_iterator it = rp().m.find(cv);
143 if (it != rp().m.end())
return (*it).second;
144 else return face_bitset();
147 void mesh_region::update_partition_iterators()
const 149 if (index_updated)
return;
150 itbegin = partition_begin();
151 itend = partition_end ();
152 index_updated =
true;
154 mesh_region::const_iterator
155 mesh_region::partition_begin( )
const 158 if (region_size < num_threads())
160 if (this_thread() == 0)
return rp().m.begin();
161 else return rp().m.end();
164 (std::ceil(static_cast<scalar_type>(region_size)/
165 static_cast<scalar_type >(num_threads())));
166 size_type index_begin = partition_size * this_thread();
167 if (index_begin >= region_size )
return rp().m.end();
169 const_iterator it = rp().m.begin();
170 for (
size_type i=0;i<index_begin;++i) ++it;
174 mesh_region::const_iterator
175 mesh_region::partition_end( )
const 178 if (region_size < num_threads())
return rp().m.end();
181 (std::ceil(static_cast<scalar_type>(region_size)/
182 static_cast<scalar_type >(num_threads())));
183 size_type index_end = partition_size * (this_thread() + 1);
184 if (index_end >= region_size )
return rp().m.end();
186 const_iterator it = rp().m.begin();
187 for (
size_type i=0;i<index_end && it!=rp().m.end();++i) ++it;
191 mesh_region::const_iterator mesh_region::begin( )
const 193 GMM_ASSERT1(p != 0,
"Internal error");
194 if (me_is_multithreaded_now() && partitioning_allowed)
196 update_partition_iterators();
199 else {
return rp().m.begin(); }
202 mesh_region::const_iterator mesh_region::end ( )
const 204 if (me_is_multithreaded_now() && partitioning_allowed)
206 update_partition_iterators();
209 else return rp().m.end();
214 if (me_is_multithreaded_now()) partitioning_allowed =
true;
215 else partitioning_allowed.all_threads() =
true;
219 auto &
mesh = *this->get_parent_mesh();
220 for (
auto cv : dal::bv_iterable_c(
index())) {
221 for (
auto &&pt :
mesh.points_of_convex(cv)) {
222 for (
auto j = 0; j < Pmin.size(); j++){
223 Pmin[j] = std::min(Pmin[j], pt[j]);
224 Pmax[j] = std::max(Pmax[j], pt[j]);
232 if (me_is_multithreaded_now()) partitioning_allowed =
false;
233 else partitioning_allowed.all_threads() =
false;
236 bool mesh_region::is_partitioning_allowed()
const 238 return partitioning_allowed;
244 dal::bit_vector& convex_index = rp().index_.thrd_cast();
245 convex_index.clear();
246 for (const_iterator it = begin(); it != end(); ++it)
248 if (it->second.any()) convex_index.add(it->first);
253 void mesh_region::add(
const dal::bit_vector &bv)
255 for (dal::bv_visitor i(bv); !i.finished(); ++i)
260 index_updated =
false;
267 index_updated =
false;
272 map_t::iterator it = wp().m.find(cv);
273 if (it != wp().m.end()) {
277 index_updated =
false;
282 map_t::iterator it = wp().m.find(cv);
283 if (it != wp().m.end()) {
285 if ((*it).second.none()) wp().m.erase(it);
288 index_updated =
false;
291 void mesh_region::clear()
293 wp().m.clear(); touch_parent_mesh();
294 index_updated =
false;
297 void mesh_region::clean()
299 for (map_t::iterator it = wp().m.begin(), itn;
300 it != wp().m.end(); it = itn)
304 if ( !(*it).second.any() ) wp().m.erase(it);
307 index_updated =
false;
313 map_t::iterator it1 = wp().m.find(cv1), it2 = wp().m.find(cv2),
317 if (it1 != ite) f1 = it1->second;
318 if (it2 != ite) f2 = it2->second;
319 if (!f1.none()) wp().m[cv2] = f1;
320 else if (it2 != ite) wp().m.erase(it2);
321 if (!f2.none()) wp().m[cv1] = f2;
322 else if (it1 != ite) wp().m.erase(it1);
324 index_updated =
false;
329 GMM_ASSERT1(p.get(),
"Use from mesh on that region before");
330 map_t::const_iterator it = rp().m.find(cv);
331 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
return false;
338 map_t::const_iterator it = rp().m.find(cv);
339 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
346 else return m.
region(
id()).is_in(cv, f);
352 bool mesh_region::is_empty()
const 354 return rp().m.empty();
360 (or_mask()[0] ==
true && or_mask().count() == 1);
365 return is_empty() || (and_mask()[0] ==
false);
368 face_bitset mesh_region::faces_of_convex(
size_type cv)
const 370 map_t::const_iterator it = rp().m.find(cv);
371 if (it != rp().m.end())
return ((*it).second) >> 1;
372 else return face_bitset();
375 face_bitset mesh_region::and_mask()
const 378 if (rp().m.empty())
return bs;
380 for (map_t::const_iterator it = rp().m.begin(); it != rp().m.end(); ++it)
381 if ( (*it).second.any() ) bs &= (*it).second;
385 face_bitset mesh_region::or_mask()
const 388 if (rp().m.empty())
return bs;
389 for (map_t::const_iterator it = rp().m.begin(); it != rp().m.end(); ++it)
390 if ( (*it).second.any() ) bs |= (*it).second;
397 for (map_t::const_iterator it = begin(); it != end(); ++it)
398 sz += (*it).second.count();
402 size_type mesh_region::unpartitioned_size()
const 405 for (map_t::const_iterator it = rp().m.begin(); it != rp().m.end(); ++it)
406 sz += (*it).second.count();
414 GMM_TRACE4(
"intersection of "<<a.id()<<
" and "<<b.id());
421 b.id() !=
size_type(-1),
"the 'all_convexes' regions " 422 "are not supported for set operations");
425 for (const_iterator it = b.begin();it != b.end(); ++it) r.wp().m.insert(*it);
430 for (const_iterator it = a.begin();it != a.end(); ++it) r.wp().m.insert(*it);
434 map_t::const_iterator
435 ita = a.begin(), enda = a.end(),
436 itb = b.begin(), endb = b.end();
438 while (ita != enda && itb != endb) {
439 if (ita->first < itb->first) ++ita;
440 else if (ita->first > itb->first) ++itb;
442 face_bitset maska = ita->second, maskb = itb->second, bs;
443 if (maska[0] && !maskb[0]) bs = maskb;
444 else if (maskb[0] && !maska[0]) bs = maska;
445 else bs = maska & maskb;
446 if (bs.any()) r.wp().m.insert(r.wp().m.end(), std::make_pair(ita->first,bs));
456 GMM_TRACE4(
"Merger of " << a.id() <<
" and " << b.id());
459 b.id() !=
size_type(-1),
"the 'all_convexes' regions " 460 "are not supported for set operations");
461 for (const_iterator it = a.begin();it != a.end(); ++it)
463 r.wp().m.insert(*it);
465 for (const_iterator it = b.begin();it != b.end(); ++it)
467 r.wp().m[it->first] |= it->second;
476 GMM_TRACE4(
"subtraction of "<<a.id()<<
" and "<<b.id());
479 b.id() !=
size_type(-1),
"the 'all_convexes' regions " 480 "are not supported for set operations");
481 for (const_iterator ita = a.begin();ita != a.end(); ++ita)
482 r.wp().m.insert(*ita);
484 for (const_iterator itb = b.begin();itb != b.end(); ++itb)
487 map_t::iterator it = r.wp().m.find(cv);
488 if (it != r.wp().m.end()){
489 it->second &= ~(itb->second);
490 if (it->second.none()) r.wp().m.erase(it);
499 if (&m1 != &m2)
return 0;
500 int r = 1, partially = 0;
501 for (
mr_visitor cv(*
this, m1); !cv.finished(); cv.next())
502 if (cv.is_face() && rg2.is_in(cv.cv(),
short_type(-1), m2))
506 if (r == 1)
return 1;
else return partially;
511 return m.regions_index().last_true()+1;
515 void mesh_region::error_if_not_faces()
const 517 GMM_ASSERT1(
is_only_faces(),
"Expecting a set of faces, not convexes");
520 void mesh_region::error_if_not_convexes()
const 525 void mesh_region::error_if_not_homogeneous()
const 528 "of convexes or a set of faces, but not a mixed set");
534 #if GETFEM_PARA_LEVEL > 1 537 bool intersect_with_mpi) :
540 if ((me_is_multithreaded_now() && s.partitioning_allowed)) {
545 if (intersect_with_mpi)
546 init(m.get_mpi_region());
549 }
else if (s.p.get()) {
550 if (intersect_with_mpi) {
551 mpi_rg = std::make_unique<mesh_region>(s);
552 mpi_rg->from_mesh(m);
553 m.intersect_with_mpi_region(*mpi_rg);
558 if (intersect_with_mpi)
559 init(m.get_mpi_sub_region(s.id()));
568 mesh_region::visitor::visitor(
const mesh_region &s,
const mesh &m,
bool)
571 if ((me_is_multithreaded_now() && s.partitioning_allowed)) {
577 }
else if (s.p.get()) {
588 bool mesh_region::visitor::next()
591 if (itb == iteb) { finished_ =
true;
return false; }
595 ++itb;
while (itb != iteb && !(*itb)) ++itb;
600 if (it == ite) { finished_=
true;
return false; }
605 if (c.none())
continue;
611 mesh_region::visitor::visitor(
const mesh_region &s) :
617 void mesh_region::visitor::init(
const dal::bit_vector &bv)
620 itb = bv.begin(); iteb = bv.end();
621 while (itb != iteb && !(*itb)) ++itb;
625 void mesh_region::visitor::init(
const mesh_region &s)
633 std::ostream & operator <<(std::ostream &os,
const mesh_region &w)
636 os <<
" ALL_CONVEXES";
639 for (
mr_visitor cv(w); !cv.finished(); cv.next())
642 if (cv.is_face()) os <<
"/" << cv.f();
648 os <<
" region " << w.id();
653 struct dummy_mesh_region_ {
655 dummy_mesh_region_() : mr() {}
void allow_partitioning()
In multithreaded part of the program makes only a partition of the region visible in the index() and ...
structure used to hold a set of convexes and/or convex faces.
region objects (set of convexes and/or convex faces)
size_type size() const
Region size, or the size of the region partition on the current thread if the region is partitioned...
Define a getfem::getfem_mesh object.
const dal::bit_vector & index() const
Index of the region convexes, or the convexes from the partition on the current thread.
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.
Describe a mesh (collection of convexes (elements) and points).
Tools for multithreaded, OpenMP and Boost based parallelization.
static T & instance()
Instance from 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.
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 prohibit_partitioning()
Disregard partitioning, which means being able to see the whole region in multirheaded code...
size_t size_type
used as the common size type in the library
static mesh_region subtract(const mesh_region &a, const mesh_region &b)
subtract the second region from the first one
bool is_only_faces() const
Return true if the region do contain only convex faces.
void bounding_box(base_node &Pmin, base_node &Pmax) const
Return the bounding box [Pmin - Pmax] of the mesh_region.
static mesh_region intersection(const mesh_region &a, const mesh_region &b)
return the intersection of two mesh regions
bool is_only_convexes() const
Return true if the region do not contain any convex face.
"iterator" class for regions.
GEneric Tool for Finite Element Methods.
gmm::uint16_type short_type
used as the common short type integer in the library
static mesh_region merge(const mesh_region &a, const mesh_region &b)
return the union of two mesh_regions
const mesh_region region(size_type id) const
Return the region of index 'id'.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.