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.