27 using face_bitset = mesh_region::face_bitset;
29 mesh_region::mesh_region(
const mesh_region &other)
30 : p(std::make_shared<impl>()), id_(
size_type(-2)), parent_mesh(0) {
31 this->operator=(other);
34 mesh_region::mesh_region()
36 partitioning_allowed{true}, parent_mesh(nullptr){
38 mark_region_changed();
42 partitioning_allowed{true}, parent_mesh(nullptr){
43 mark_region_changed();
47 p(std::make_shared<impl>()), id_(id__), type_(type),
48 partitioning_allowed{true}, parent_mesh(&m){
50 mark_region_changed();
53 mesh_region::mesh_region(
const dal::bit_vector &bv)
55 partitioning_allowed{true}, parent_mesh(nullptr){
58 mark_region_changed();
61 void mesh_region::mark_region_changed()
const{
62 index_updated.all_threads() =
false;
63 partitions_updated.all_threads() =
false;
64 serial_index_updated =
false;
67 void mesh_region::touch_parent_mesh(){
68 if (parent_mesh) parent_mesh->touch_from_region(id_);
77 r->p = std::make_shared<impl>();
85 mark_region_changed();
90 if (!parent_mesh && !from.parent_mesh){
93 partitioning_allowed.store(from.partitioning_allowed.load());
95 if (!p) p = std::make_shared<impl>();
100 else if (!parent_mesh) {
104 parent_mesh = from.parent_mesh;
105 partitioning_allowed.store(from.partitioning_allowed.load());
110 type_= from.get_type();
111 partitioning_allowed.store(from.partitioning_allowed.load());
117 partitioning_allowed =
true;
121 mark_region_changed();
125 bool mesh_region::compare(
const mesh &m1,
126 const mesh_region &mr,
127 const mesh &m2)
const {
128 if (&m1 != &m2)
return false;
129 if (!p && !mr.p)
return (id_ == mr.id_);
132 if (p && !(mr.p))
return false;
133 if (!p && mr.p)
return false;
135 if (p->m != mr.p->m)
return false;
139 face_bitset mesh_region::operator[](
size_t cv)
const{
140 auto it = rp().m.find(cv);
141 if (it != rp().m.end())
return it->second;
145 void mesh_region::update_partition_iterators()
const{
146 if ((partitions_updated.thrd_cast() ==
true))
return;
147 itbegin = partition_begin();
148 itend = partition_end ();
149 partitions_updated =
true;
151 mesh_region::const_iterator
152 mesh_region::partition_begin( )
const{
153 auto region_size = rp().m.size();
154 if (region_size < partitions_updated.num_threads()){
156 if (partitions_updated.this_thread() == 0)
return rp().m.begin();
157 else return rp().m.end();
159 auto partition_size =
static_cast<size_type>
160 (std::ceil(
static_cast<scalar_type
>(region_size)/
161 static_cast<scalar_type
>(partitions_updated.num_threads())));
162 auto index_begin = partition_size * partitions_updated.this_thread();
163 if (index_begin >= region_size )
return rp().m.end();
165 auto it = rp().m.begin();
166 for (
size_type i = 0; i != index_begin; ++i) ++it;
170 mesh_region::const_iterator
171 mesh_region::partition_end( )
const{
172 auto region_size = rp().m.size();
173 if (region_size< partitions_updated.num_threads())
return rp().m.end();
175 auto partition_size =
static_cast<size_type>
176 (std::ceil(
static_cast<scalar_type
>(region_size)/
177 static_cast<scalar_type
>(partitions_updated.num_threads())));
178 auto index_end = partition_size * (partitions_updated.this_thread() + 1);
179 if (index_end >= region_size )
return rp().m.end();
181 auto it = rp().m.begin();
182 for (
size_type i = 0; i < index_end && it != rp().m.end(); ++i) ++it;
186 mesh_region::const_iterator mesh_region::begin()
const{
187 GMM_ASSERT1(p != 0,
"Internal error");
189 update_partition_iterators();
192 else return rp().m.begin();
195 mesh_region::const_iterator mesh_region::end()
const{
197 update_partition_iterators();
200 else return rp().m.end();
204 partitioning_allowed =
true;
208 auto &
mesh = *get_parent_mesh();
209 for (
auto &&cv : dal::bv_iterable_c{
index()}) {
210 for (
const auto &pt :
mesh.points_of_convex(cv)) {
211 for (
auto j = 0; j != Pmin.size(); ++j){
212 Pmin[j] = std::min(Pmin[j], pt[j]);
213 Pmax[j] = std::max(Pmax[j], pt[j]);
220 partitioning_allowed =
false;
223 bool mesh_region::is_partitioning_allowed()
const{
224 return partitioning_allowed;
227 void mesh_region::update_index()
const{
229 rp().index_.thrd_cast() : rp().serial_index_;
230 if (convex_index.card() != 0) convex_index.clear();
231 for (
auto &&pair : *
this){
232 if (pair.second.any()) convex_index.add(pair.first);
237 GMM_ASSERT1(p,
"Use from_mesh on that region before");
239 if (!(index_updated.thrd_cast() ==
true)){
241 index_updated =
true;
246 if (!serial_index_updated){
248 serial_index_updated =
true;
250 return rp().serial_index_;
254 void mesh_region::add(
const dal::bit_vector &bv){
255 for (dal::bv_visitor i(bv); !i.finished(); ++i){
259 mark_region_changed();
265 mark_region_changed();
269 auto it = wp().m.find(cv);
270 if (it != wp().m.end()){
273 mark_region_changed();
278 auto it = wp().m.find(cv);
279 if (it != wp().m.end()) {
281 if (it->second.none()) wp().m.erase(it);
283 mark_region_changed();
287 void mesh_region::clear(){
290 mark_region_changed();
293 void mesh_region::clean(){
294 for (map_t::iterator it = wp().m.begin(), itn;
295 it != wp().m.end(); it = itn) {
298 if (!(*it).second.any()) wp().m.erase(it);
301 mark_region_changed();
305 auto it1 = wp().m.find(cv1);
306 auto it2 = wp().m.find(cv2);
307 auto ite = wp().m.end();
310 if (it1 != ite) f1 = it1->second;
311 if (it2 != ite) f2 = it2->second;
312 if (!f1.none()) wp().m[cv2] = f1;
313 else if (it2 != ite) wp().m.erase(it2);
314 if (!f2.none()) wp().m[cv1] = f2;
315 else if (it1 != ite) wp().m.erase(it1);
317 mark_region_changed();
321 GMM_ASSERT1(p,
"Use from mesh on that region before");
322 auto it = rp().m.find(cv);
323 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
return false;
329 auto it = rp().m.find(cv);
330 if (it == rp().m.end() ||
short_type(f+1) >= MAX_FACES_PER_CV)
336 else return m.region(
id()).is_in(cv, f);
340 bool mesh_region::is_empty()
const{
341 return rp().m.empty();
346 (or_mask()[0] ==
true && or_mask().count() == 1);
350 return (
id() !=
size_type(-1)) && (is_empty() || (and_mask()[0] ==
false));
353 face_bitset mesh_region::faces_of_convex(
size_type cv)
const{
354 auto it = rp().m.find(cv);
355 if (it != rp().m.end())
return ((*it).second) >> 1;
356 else return face_bitset();
359 face_bitset mesh_region::and_mask()
const{
361 if (rp().m.empty())
return bs;
363 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
364 if ( (*it).second.any() ) bs &= (*it).second;
368 face_bitset mesh_region::or_mask()
const{
370 if (rp().m.empty())
return bs;
371 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
372 if ( (*it).second.any() ) bs |= (*it).second;
378 for (
auto it = begin(); it != end(); ++it)
379 sz += (*it).second.count();
383 size_type mesh_region::unpartitioned_size()
const{
385 for (
auto it = rp().m.begin(); it != rp().m.end(); ++it)
386 sz += (*it).second.count();
392 GMM_TRACE4(
"intersection of "<<a.id()<<
" and "<<b.id());
399 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
400 "are not supported for set operations");
402 for (const_iterator it = b.begin();it != b.end(); ++it) r.wp().m.insert(*it);
406 for (const_iterator it = a.begin();it != a.end(); ++it) r.wp().m.insert(*it);
410 auto ita = a.begin(), enda = a.end(),
411 itb = b.begin(), endb = b.end();
413 while (ita != enda && itb != endb) {
414 if (ita->first < itb->first) ++ita;
415 else if (ita->first > itb->first) ++itb;
417 face_bitset maska = ita->second, maskb = itb->second, bs;
418 if (maska[0] && !maskb[0]) bs = maskb;
419 else if (maskb[0] && !maska[0]) bs = maska;
420 else bs = maska & maskb;
421 if (bs.any()) r.wp().m.insert(r.wp().m.end(), std::make_pair(ita->first,bs));
430 GMM_TRACE4(
"Merger of " << a.id() <<
" and " << b.id());
433 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
434 "are not supported for set operations");
435 for (
auto it = a.begin();it != a.end(); ++it){
436 r.wp().m.insert(*it);
438 for (
auto it = b.begin();it != b.end(); ++it){
439 r.wp().m[it->first] |= it->second;
447 GMM_TRACE4(
"subtraction of "<<a.id()<<
" and "<<b.id());
450 b.id() !=
size_type(-1),
"the 'all_convexes' regions "
451 "are not supported for set operations");
452 for (
auto ita = a.begin();ita != a.end(); ++ita)
453 r.wp().m.insert(*ita);
455 for (
auto itb = b.begin();itb != b.end(); ++itb){
456 auto cv = itb->first;
457 auto it = r.wp().m.find(cv);
458 if (it != r.wp().m.end()){
459 it->second &= ~(itb->second);
460 if (it->second.none()) r.wp().m.erase(it);
469 if (&m1 != &m2)
return 0;
470 int r = 1, partially = 0;
471 for (
mr_visitor cv(*
this, m1); !cv.finished(); cv.next())
472 if (cv.is_face() && rg2.is_in(cv.cv(),
short_type(-1), m2))
476 return r == 1 ? 1 : partially;
480 return m.regions_index().last_true()+1;
483 void mesh_region::error_if_not_faces()
const{
484 GMM_ASSERT1(
is_only_faces(),
"Expecting a set of faces, not convexes");
487 void mesh_region::error_if_not_convexes()
const{
491 void mesh_region::error_if_not_homogeneous()
const{
493 "of convexes or a set of faces, but not a mixed set");
497 #if GETFEM_PARA_LEVEL > 1
499 mesh_region::visitor::visitor(
const mesh_region &s,
const mesh &m,
500 bool intersect_with_mpi) :
508 if (intersect_with_mpi)
509 init(m.get_mpi_region());
511 init(m.convex_index());
512 }
else if (s.id() ==
size_type(-2) && s.p.get()) {
513 if (intersect_with_mpi) {
514 mpi_rg = std::make_unique<mesh_region>(s);
515 mpi_rg->from_mesh(m);
516 m.intersect_with_mpi_region(*mpi_rg);
521 GMM_ASSERT1(s.id() !=
size_type(-2),
"Internal error");
522 if (intersect_with_mpi)
523 init(m.get_mpi_sub_region(s.id()));
525 init(m.region(s.id()));
532 mesh_region::visitor::visitor(
const mesh_region &s,
const mesh &m,
bool)
540 init(m.convex_index());
541 }
else if (s.id() ==
size_type(-2) && s.p.get()) {
544 GMM_ASSERT1(s.id() !=
size_type(-2),
"Internal error");
545 init(m.region(s.id()));
552 bool mesh_region::visitor::next(){
562 while (itb != iteb && !(*itb)) ++itb;
566 if (it == ite) { finished_=
true;
return false; }
571 if (c.none())
continue;
577 mesh_region::visitor::visitor(
const mesh_region &s) :
582 void mesh_region::visitor::init(
const dal::bit_vector &bv){
584 itb = bv.begin(); iteb = bv.end();
585 while (itb != iteb && !(*itb)) ++itb;
589 void mesh_region::visitor::init(
const mesh_region &s){
596 std::ostream & operator <<(std::ostream &os,
const mesh_region &w){
598 os <<
" ALL_CONVEXES";
600 for (mr_visitor cv(w); !cv.finished(); cv.next()){
602 if (cv.is_face()) os <<
"/" << cv.f();
607 os <<
" region " << w.id();
612 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.